Well you probably know what they are gonna say:
Git Rebase is sooooo good dude! It is CLEAN, making your history liner and organized. And you will never see that weird merge joint point messing around in your branch. What? You don't know how to use? You don't even know Rebase? Ah you suck dude!...
Normally you have two options when you try to combine two branches:
Rebase, and the discussion or argue like above lasts endlessly. But chill first, let's put this noob flaming aside and talk about what is
What is rebase?
Say now we have two branches:
feature. In your
master branch you have
commit 1 which has one file containing a character: "A". Then
commit 2 changed "A" character to "B". The
feature branch comes out from
commit 1 and has two commits.
commit 3 changes character "A" to "C", and
commit 4 keeps that file same(Let's assume you change some other files so this is still a valid commit).
Now when you rebase master into feature, the ideal result should be like:
You can find a lot of more elaborated descriptions about how to do this at
But these are definitely not what I want to talk about.
So you really think you can do that? A big NO! If you follow the official tutorial, you will get a warning and merge conflict solving request when you do rebase.
This is because at the last picture, the commit commit 3 is a CHANGE
replacing "A" to "C":
but now this CHANGE has been CHANGED to
replacing "B" to "C":
Rebase is replaying
commit 3 and
commit 4 on top of
commit 2, and it realizes that the commit 3 can't be done exactly same as before. It will challenge you and let you solve the issue.
From Visual Studio Code we can see two different changes conflicting each other.
(BTW: In Visual Studio or Visual Studio Code, you normally will see Current Change and Incoming Change, here current change is what from
masterbranch and incoming change is what from
Put out conflictions and fire
Now you have three choices to fix this situation:
- Keep the current change. It means you choose the change from master branch
- Keep the incoming change. You choose the change from feature branch
- Keep both of them or change to something else. You are creative aren't you? I personally don't favor this idea cause you are rewriting history fundamentally. But it is not acceptable since rebase itself is also a rewriting behavior. If you do have new ideas except those two before, I recommend you choose one of two previous choices and finish rebase first, then you can safely patch your new thoughts at next new commit.
Conflictions after solving
Now you are swearing to me. Yes you are.
Because that god damn error prompt in Git showing up again, right? So what is going on?
Truth is, there will be further conflictions to solve if:
You choose to keep current change and you have changes to the same file after that first reapplied commit:
From this picture, you see the
commit 4 adds a new line "A" below "C" after
commit 3. If you rebase
master now and choose current change, after git runs continues rebase, another confliction will wait for you to solve:
(BTW: Steps in rebase means nth of current reapplied commit patch)
Now this change:
replacing "C" to "CA"
has been modified to:
replacing "B" to "CA"
Here again, we have another confliction to solve. And the solution can refer to previous topic.
Messy remote after push
Git won't easily stand out from VCS without cooperation with remote hosts. It also brings more puzzles when we enjoy it's benefits.
After we finish rebase locally, you definitely want to "Sync" with remote host, either your company repo host or just Github, where the "Dirty" of rebase befall down on you.
Let take a look what is happening:
After you finish rebase locally and use
git push to push to remote, you probably will see:
It says "rejected" and asks you to pull first. What the hell?
The thing is, rebase is rewriting history commits, even if everything is the same as hell. It rewrite every commit in the feature branch, or the branch you rebase from, here it is
After rebase, Git generates different hash for every commits of branch
feature and it checks with remote when you push. Here Git detected difference between local and remote branches, treat it as a diverged commit push, and ask you to solve it by pulling + merge, or another trick that you fetch remote Head, manually add it to your local Head and push again.
But no matter what way you choose, after you pull/fetch, merge and crying to push, you will see this horrible commit history at both local and remote:
I really can't think anything worse than this except showing single digit in my bank account...
Here the way to solve this issue is quite simple:
You FORCE PUSH it: git push --force
Ok this is something we describe as "ridiculous". I heard news saying some really pissed off programmer shoot his colleagues and part of the reason is.....he can't bear colleagues' force push to remote repo.
First thing first, Force Push destroys remote copy and that could be devastating. But we should talk about it case by case. Here if you are working alone with your own feature, and no one cares about your branch, you can just safely force push it and get a clean result. Or you can secure it by saving a copy of the branch by creating a same branch with different name in case you are really paranoid about it.
Hopefully you have a good journey with Git and those suggestion are helpful to you.