Week 7Day 5 - "I could rebase the world"
Migrating commits
We are almost at the end our our journey with the rebase tool and have one more stop before we start looking at other features of Git.
In the trenches...
Rob was sitting with his head on the table.
Every few seconds he would lift it up before thumping it down again.
It was obvious to everyone in the office that Rob had done something wrong.
In the end it was John who broke the rhythmic bass drum.
He pulled up a chair next to the desk.
"Come on Rob," started John, "What's eating you?"
"Well, I have been working away, committing to a branch, but it wasn't the right one."
He looked like he was almost in tears.
John frowned, "Can't you just move a new branch forward and then rewind the other one?"
"No." His voice was tired and weary.
"The ancestor of the branch isn't right. I thought I had branched from master, but I'd actually branched from a dev branch. Now I can't find a way to bring my commits back. Short of cherry picking each one, but I have over fifty of them. Guess it's time to start scripting."
John smiled and shook his head, "Don't worry Rob, I have a better plan"
Cherry picking is a method of copying the contents of one commit into another and is something that we will pick up on later, but we will first look at our final use of rebase.
Imagine the scenario painted above.
You made a branch, have been merrily committing for hours, before realising that actually you branched from the wrong ancestor.
In Git, this isn't a problem.
Things get complicated if you've been doing more advanced operations during this period, but if you have been simply adding commits, we can use rebase to migrate the tree of commits to a different ancestor.
Take the example we have been working on. Currently we have a master branch and a wonderful branch, and these differ, though they have a common ancestor.
Let us say we are currently sitting on the wonderful branch, but we thought we were on master and we created a new branch called develop.
john@satsuki:~/coderepo$ git checkout -b develop
Switched to a new branch 'develop'
john@satsuki:~/coderepo$
Now let us commit a few files and see what we can do about fixing our problem.
john@satsuki:~/coderepo$ echo "new dev work" >> newfile3
john@satsuki:~/coderepo$ git commit -a
[develop eb7f633] Some new dev work
1 files changed, 1 insertions(+), 0 deletions(-)
john@satsuki:~/coderepo$ echo "newer dev work" >> newfile2
john@satsuki:~/coderepo$ git commit -a
[develop 5e0964b] More new deving
1 files changed, 1 insertions(+), 0 deletions(-)
john@satsuki:~/coderepo$
Let us use our little log alias and see the work we just did on our "master" branch.
john@satsuki:~/coderepo$ git logg -n8
* 5e0964b (HEAD, develop) More new deving
* eb7f633 Some new dev work
* 4d91aab (wonderful) Updated another file again
* 1ffe37f Updated another file with 2 edits
| * 5167cce (keeprebase) Updated another file again
| * 551086e Updated another file with 2 edits
| * f8d5100 (master) Finished new dev
| * 1968324 Start new dev
|/
john@satsuki:~/coderepo$
Whoops! The commits were supposed to be on a branch that stemmed from master, not one that stems from wonderful.
In other words, develop stems from wonderful, when it should have stemmed from master.
This is where git rebase comes to our assistance once more.
With one command, we can move those commits to a branch that stems from master.
john@satsuki:~/coderepo$ git rebase --onto master wonderful develop
First, rewinding head to replay your work on top of it...
Applying: Some new dev work
Applying: More new deving
john@satsuki:~/coderepo$ git logg -n8
* aed985c (HEAD, develop) More new deving
* af3c6d7 Some new dev work
| * 5167cce (keeprebase) Updated another file again
| * 551086e Updated another file with 2 edits
|/
* f8d5100 (master) Finished new dev
* 1968324 Start new dev
| * 4d91aab (wonderful) Updated another file again
| * 1ffe37f Updated another file with 2 edits
|/
john@satsuki:~/coderepo$
Notice in the output above that we have used our git rebase tool with a new --onto master parameter.
Basically the syntax above is stating that we would like to take all of the commits between the points wonderful and develop and place them onto master instead.
A little housework
To clean up our repository, we are going to delete our keeprebase branch.
john@satsuki:~/coderepo$ git branch -D keeprebase
Deleted branch keeprebase (was 5167cce).
john@satsuki:~/coderepo$
We have reached the end of our tour with the rebase tool.
It is exceedingly powerful and is definitely one of the tools that you should understand before using.
As stated before, do not forget the fact that rebasing changes history.
In all cases that we have used rebase, commit IDs have been changed and therefore you must be very careful when using it.
|