Sunday, September 30, 2012

GIT Rebase on Remote branches

Ever finished up work on some code, commit it with git only to realize that you forgot to create you feature branch before you started?

If this has happened to you at some point you know that all your work is now on your local master brache while work on the remote master has continued at steady pace, with commits from other team members stacking up. You can not push because git wont let you. And if you pull you will end up with a fat ugly merge commit that is pretty far from the nice rebase your were aiming at that would make the commit history a joy to read.

What you want

Your usual modus operandi looks something like this:

1. Get to work in the morning, get current and branch off before starting today's tasks: 

git checkout master
git pull
git checkout -b work

(Throughout the text I will continuously checkout branches instead of writing which branch I am on.)

2. Finish up your nice coding work and then:

git commit -a -m "Finished cool feature"

3. Now, before pushing, you want to get current again and put your own commits "on top" of any other ones that were pushed while you where busy finishing up your feature. So:

git checkout master
git pull
git checkout work
git rebase master

4. And now that your commits will not cause a merge commit but instead can be fast forwarded, it is time to share with rest of the team:

git checkout master
git merge work
git push

5. Go for coffee.

What you have

But right now all that is Utopia. You forgot all about creating that work branch and all your nice code is committed on (what by now is) your outdated local master branch.
Your world looks like this:

git push

 ! [rejected]        master -> master (non-fast-forward)
error: failed to push some refs to 'some-repo'
To prevent you from losing history, non-fast-forward updates were rejected
Merge the remote changes (e.g. 'git pull') before pushing again.  See the
'Note about fast-forwards' section of 'git push --help' for details. 

How to fix it

There is still a chance to avoid ridicule if you remember that there is very little difference between local and remote branches it git. You ought to be able to rebase your local master on its remote counter part. Here is how:

1. If you are the slightest bit uncomfortable with the operation. Back up your repository!
It is dirt cheap and very simple.

cp -a your-repo-dir your-repo-dir.bak

2. Download the objects and refs from the remote repo

git checkout master
git fetch

3. Now that your index is in sync with the remote repository's you can rebase master on origin/master.

git checkout master
git rebase origin/master

4. After resolving any conflicts in the same way as you would normally to your ready to push.

git push

5. Go for coffee and forget all about this little mishap!

(There is also a short hand combining steps 3 and 4: git pull --rebase.)


I might be helpful to know that when you do a git pull it is actually a shortcut for doing a git fetch followed by a git merge.

git branch will list your local branches dy default. Use git branch -r to list remote branches or git branch -a to list all branches.

No comments:

Post a Comment