Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Remove other peoples' commits on my branch after rebase gone wrong

I got myself into some git-funk here. I need to git-fu myself out of this.

I joined a new team and created a feature branch:

git checkout -b feature_branch

Made some changes and then committed/pushed them up to the branch.

git commit -am "Changes"
git push origin feature_branch

Someone left a review on my PR, so I made the changes, and then checked out to master and rebased my branch before committing/pushing again to that branch:

// from feature_branch make some changes
git commit -am "New changes"
git checkout master
git checkout feature_branch
git rebase origin/master
git push feature_branch

Once I did this, I noticed my PR (on Github) picked up someone elses' commit. I was then informed that the typical method within this new team is to checkout to master and merge back into my branch INSTEAD of rebasing.

Here is the funky part now -- I started mucking around with git reset --hard and picked the commit I wanted that was before that commit from someone else.

All was well, or so I thought. I then pushed that up and it seemed to have removed that other persons' commit from my PR.

I checked this morning and now there are a bunch of other commits from someone else that got picked up.

So now I'm in this weird state. I look at my PR and there are almost 30 commits (with 6 from different people). The actual diff (files changed) are only the files that I touched, which is good, but the history itself looks ridiculous.

What's the best approach to clean this up? Everything is suggesting to use git rebase, however, I was advised not to use rebase.

Unfortunately, I need to keep this branch. What's the best way to clean it up and remove all the other commits except only mine? Just reset it completely and then cherry-pick the changes back onto the branch?

Please help :|

EDIT: Here's an example of what the history looks like:

Commits on Jul 30, 2018
<SOMEONE ELSES>

Commits on Jul 31, 2018
<SOMEONE ELSES>
<MY ORIGINAL COMMIT>
<SOMEONE ELSES>

Commits on Aug 1, 2018
<SOMEONE ELSES>
<MY COMMIT [Merge branch master into my feature branch]>
<MY COMMIT>
<SOMEONE ELSES>
<MY COMMIT>
<MY COMMIT>
<SOMEONE ELSES>
<MY COMMIT>

etc etc
like image 547
bob_cobb Avatar asked Aug 03 '18 23:08

bob_cobb


2 Answers

// from feature_branch make some changes
git commit -am "New changes"
git checkout master
git checkout feature_branch
git rebase origin/master
git push feature_branch

Once I did this, I noticed my PR (on Github) picked up someone elses' commit.

If all you did was rebase on top of origin/master that should not have been possible.

However, this sequence is a bit fishy. You never do a git fetch so origin/master is not known to be up to date. If a rebase did happen, git push feature_branch should have failed because a rebase cannot be fast forwarded. You would have had to use git push -f feature_branch.

I suspect something else went wrong that you're not showing us. A complete history of your commands would help.

The proper sequence for updating a branch with rebase is this.

# Update all your remotes
git fetch

# Rebase your branch on top of origin/master
git checkout feature_branch
git rebase origin/master

# Force push the branch
git push -f

Fortunately your old commits are not lost after a rebase, they're just not connected to anything. To find them, use git reflog. This will show every time HEAD (ie. your current checkout) changed.

In the reflog, look for something like this...

081abed HEAD@{8}: rebase finished: returning to refs/heads/feature_branch
081abed HEAD@{9}: rebase: the last commit message from your branch
0a5b366 HEAD@{10}: rebase: another commit message
e9c4d18 HEAD@{11}: rebase: the first commit message from your branch
e6780bf HEAD@{13}: rebase: checkout origin/master
0ee63b1 HEAD@{14}: checkout: moving from master to feature_branch

0ee63b1 will be your old branch tip. git reset --hard 0ee63b1 and you've undone the rebase.


There's an alternative explanation: that you've made your PR against the wrong branch. Double check that.

like image 102
Schwern Avatar answered Oct 10 '22 18:10

Schwern


What's the best approach to clean this up? Everything is suggesting to use git rebase, however, I was advised not to use rebase.

Even though the team does not use a rebase workflow themselves, it might be the better approach to fix unmerged branches. As long as you are sure that no one else is using and you are aware of the possible implications if that's not the case.

Note: I assume your remote is named origin and that the branch was created on master. If that's not the case, just replace them with the appropriate ones.

Before anything, stash all modifications (if any):

git stash save

And checkout to your branch:

git checkout mybranch

(Recommended) Backup the branch as is with a temporary tag:

git tag mybranch_bkp_rebase

Rebase

As mentioned, you can rebase to the point where the branch was created and delete the lines whose commits are not relevant to your branch.

git rebase -i "$(git merge-base origin/master HEAD)"

With that, the only commits left in your branch will be the ones that already were there when you created the branch, plus the commits from the lines that weren't deleted.

(Optional) After checking that everything is in order, you can rebase to the current master:

git rebase origin/master

Reset

If you don't want to rebase, you could just reset to a previous known good state. That could be either a commit in your own branch, the commit it was created on or the current master:

# Pick one
last_known_good_rev=hash_of_last_good_commit
last_known_good_rev="$(git merge-base origin/master HEAD)"
last_known_good_rev='origin/master'
git reset --hard "$last_known_good_rev"

Then check with git log for commits that might be missing:

git log --oneline mybranch_bkp_rebase..HEAD

And cherry-pick them:

git cherry-pick hash1 hash2 hash3
like image 32
kelvin Avatar answered Oct 10 '22 17:10

kelvin