You can think of git commits like a long chain. Each time you make a commit, you add one more link in the chain. The problem is that sometimes that chain can split into two chains like this:
D
|
C C2
| |
B --
|
A
What most people do when they want to move C2 back into the original chain is what is called a merge and it looks like this:
E
| \
D |
| |
C C2
| |
B --
|
A
In which E is a commit which combines the changes of C, D, and C2 into a new commit . However, with branches and then branches off of branches this can quickly lead to a spaghetti looking history. Instead, let's see what happens when you switch to the branch with commit C2 (let's call it 'dev') and run rebase on the main line (let's call it 'master'). So
git checkout dev
git rebase master
C2
|
D
|
C
|
B
|
A
This history is much cleaner now, as C2 was simply moved to the end of the line. This is what rebase does. Note that master is still pointing to 'D', and dev is pointing to the new 'C2' location.
Top comments (8)
Great post to exemplify rebase! Just remember that for pushing changes to remote it could be better to git push --force-with-lease instead of the typical git push --force. The former would watch for any changes you don't have in your local branch.
As the other Daniel pointed out never force push to the master branch and always let relevant people know when you do for another. What do do with your rebased changes (in terms of pushing) probably deserves a separate post all together but the main goal here is to not have to force push at all. In the example I've given no force push is needed for the main branch (only the dev branch if it is going to continue)
If you force push to a main branch everyone will hate you. I don't think you should give this advice in a posting for git beginners. Just because you can do that doesn't mean it's the right thing to do....
May the --force be with you! Seriously, never force push to the master. It's not like you have to with rebase. Don't understand the advice though.
You should point out that when doing rebase you're in fact changing commit history for the commit c2. While the changes in c2 still apply, the commit id will change. That is not obvious to any git beginner. So to be more clear you should rename the c2 to c2'.
This is true but I wonder if a beginner will understand the significance of this...
Thanks for the guide, I've never been clear on this! In the last diagram, does C2 overwrite the changes from D? Or does it functionally do the same thing a regular merge?
C2 will apply the changes on top of D as if it were a regular merge. As such, you can get merge conflicts at this stage but after you merge them your history will still be cleaner.