git: Merge Branches but Keep Commit History

佐手、 提交于 2019-12-02 20:49:36

Answer

Here is a workflow that you can use that does just what you need it to do.

git checkout master
git pull --rebase                             (1)
git checkout new_feature                      
<do a bunch of commits>
git rebase master                             (2)
git checkout master
git merge new_feature                         (3)
git branch -D new_feature                     (4)

Explanation

(1) git pull --rebase will first fetch origin/master and then replay your local master on top of it. Note in the example log that your local commits are on top of your "local remote HEAD pointer."

> git log --oneline --all -10 --decorate

d34d34c (HEAD, master) Local commit message.
d3434r2 Local commit message.
d234d4c Local commit message.
er3ede3 (origin/master, origin/HEAD) Remote commit message.
sfe3fd3 Remote commit message.

You can now checkout and work on your new_feature branch for a while. When you're done...

(2) git rebase master will replay new_feature on top of master. Again, your local commits remain on top of your "local remote HEAD pointer."

> git log --oneline --all -10 --decorate

fc5773d (new_feature) Local new_feature commit.
9282838 Local new_feature commit.
d34d34c (HEAD, master) Local commit.
d3434r2 Local commit.
d234d4c Local commit.
er3ede3 (origin/master, origin/HEAD) Remote commit.
sfe3fd3 Remote commit.

The rebase command just put new_feature ahead of master, and to align them you need to run...

(3) git merge new_feature, which will do a fast-forward merge. Now HEAD, new_feature, and master all point to the same commit.

> git log --oneline --all -10 --decorate

fc5773d (HEAD, new_feature, master) Local new_feature commit.
9282838 Local new_feature commit.
d34d34c Local commit.
d3434r2 Local commit.
d234d4c Local commit.
er3ede3 (origin/master, origin/HEAD) Remote commit.
sfe3fd3 Remote commit.

(4) After that, you can safely delete the new_feature branch. Your final log before pushing will look like this:

> git log --oneline --all -10 --decorate

fc5773d (HEAD, master) Local new_feature commit 2
9282838 Local new_feature commit.
d34d34c Local commit.
d3434r2 Local commit.
d234d4c Local commit.
er3ede3 (origin/master, origin/HEAD) Remote commit.
sfe3fd3 Remote commit.

It's unnecessary to run git rebase new_feature on the master branch after you've run git rebase master on the new_feature branch. After you've run git rebase master on the new_feature branch, you can then merge new_feature into master - it will be a fast-forward merge and won't introduce a merge commit.

The reason why git rebase new-feature isn't playing all the new-feature commits on top of master is because git recognizes master already is at the base of new feature - we performed that step with git rebase master - and that it would just be rebasing on itself. So instead it just fast-forwards to new-feature.

Also, you don't need to worry about pushing commits that reside below your remote/master tip -- the remote will reject your push should you try (unless you provide the -f option, which, don't). And, if your local master is tracking your remote master, git status will tell if your local has diverged from you remote branch.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!