2019年10月14日 星期一

[Git 文章收集] Differences between git merge and git rebase

Source From Here
Preface
Merging and rebasing are the two most popular way to applying changes from one branch into another one. They both give you the same result at the end, so let’s talk about differences. Briefly:
git merge apply all unique commits from branch A into branch B in one commit with final result
git merge doesn’t rewrite commit history, just adds one new commit
git rebase gets all unique commits from both branches and applies them one by one
git rebase rewrites commit history but doesn’t create extra commit for merging


Detailed
Default git strategy for merging is simple three-way merging. It means that Git uses the two snapshots (every commit has snapshot for full working directory) pointed to by the branch tips and the common ancestor of the two and then make result commit with applied changes from both branches.

Let’s say we have two branches feature1 and feature2 that have diverged from a common commit “a” to have four commits each.



Now we want to combine both the features into a single branch. Merge and Rebase are our options. Let’s see what each of them can do.

Git Merge:
Merge will seem like a fairly obvious thing, if you look at the end result. It is pretty much like taking two threads and tying them up in a knot:



Here the commit ‘b’, has the information regarding all the commits in feature1 and feature2. So, Merge preserves the history of the repository.

Git Rebase:
Rebase on the other hand doesn’t preserve the history. It quite literally re-bases one branch on top of the other i.e., it changes the base of the branch. Let’s see rebasing with the same example. Let’s say I want to rebase feature1 onto feature2, what that means is that I want all the commits in the branch feature1 on top of the commits of feature2. So, after rebase your commit history would look like the following:



As you see in the picture, the base of feature1 which was previously the commit “a”, has been shifted to the green commit “4”. Hence the name Re-Base. Here feature1 is sitting on top of feature2 as opposed to being on “a”.

Both Merge and Rebase have their pros and cons. Merge keeps the history of the repository but can make it hard for someone to understand and follow what’s going on at a particular stage when there are multiple merges. Rebase on the other hand ‘rewrites’ history (read - creates new history) but makes the repo look cleaner and is much easier to look at.

When to use:
* git merge is a default behavior when you use git pull. Use it as default if you are not bothering about commit history and want to avoid problems
* use git rebase to make your commit history more clear and consistent (use it only before pushing to remote servers to keep your name and karma clean)
* use git rebase for temporary local branches — they are not necessary for public commit history and won’t make problems
* use git rebase -i (interactive) for rewriting your local commit history into pretty one before pushing it on the remote server.


Real Example
Let's use few git commands to see how git merge and git rebase work.

Merged branch `iss53` back to branch `master`
Check commit history before merge:
# git status
# On branch iss53
nothing to commit, working directory clean


# git log --oneline | head -n 3
2b108f6 C2
8f30e1a C1

bb134c5 Update 105M.img


# git checkout master
Switched to branch 'master'

# git log --oneline | head -n 2
d3f9908 C3
bb134c5 Update 105M.img
faa8827 Upload large file >50M

Now it's time to do the merge in branch `master`:
# git rebase iss53
  1. Merge branch 'iss53'  
  2.   
  3. # Please enter a commit message to explain why this merge is necessary,  
  4. # especially if it merges an updated upstream into a topic branch.  
  5. #  
  6. # Lines starting with '#' will be ignored, and an empty message aborts  
  7. # the commit.  


# git log --oneline | head -n 5
8a747e7 Merge branch 'iss53'
d3f9908 C3
2b108f6 C2
8f30e1a C1
bb134c5 Update 105M.img


# git checkout iss53
Switched to branch 'iss53'

# git log --oneline | head -n 3
2b108f6 C2
8f30e1a C1
bb134c5 Update 105M.img

Rebase feature1 onto feature2
Again, let's check the status of each branch:
# git log --oneline | head -n 3
664eb38 F2
a3033da F1

bb134c5 Update 105M.img


# gis
# On branch feature1
nothing to commit, working directory clean


# git checkout feature2 // Switch to branch `feature2`

# gis
# On branch feature2
nothing to commit, working directory clean


# git log --oneline | head -n 3
a171eef F2_2
c6fd8f1 F2_1

bb134c5 Update 105M.img

Now let's rebase branch `feature1` to branch `feature2` (After switching back to `feature1`):
# git rebase feature2
First, rewinding head to replay your work on top of it...
Applying: F1
Applying: F2


# git log --oneline | head -n 5
4aefbe2 F2
26e83b4 F1

a171eef F2_2
c6fd8f1 F2_1
bb134c5 Update 105M.img


Supplement
Git: 比較 Merge Squash 與 Rebase Squash
用於合併不同分支時,希望在合併後只有一個提交記錄。...

Quora - What is the difference between rebase and merge in Git?
3.2 使用 Git 分支 - 分支和合併的基本用法
【狀況題】剛才的 Commit 後悔了,想要拆掉重做…

沒有留言:

張貼留言

[Git 常見問題] error: The following untracked working tree files would be overwritten by merge

  Source From  Here 方案1: // x -----删除忽略文件已经对 git 来说不识别的文件 // d -----删除未被添加到 git 的路径中的文件 // f -----强制运行 #   git clean -d -fx 方案2: 今天在服务器上  gi...