git:合并分支但保留提交历史

git: Merge Branches but Keep Commit History

在我的 git 工作流程中,我们有一个主存储库和一个分支,master。每个人都从远程主机拉取,每个人都向远程主机推送。我想在准备功能时在自己的分支机构工作。到目前为止,我的历史是这样的:

git pull --rebase
git checkout -b new_feature
<make some commits>
git checkout master
git pull --rebase

现在我想合并分支,这是我需要的:

  1. 我的本地 master 分支中没有合并提交。
  2. 我的 new_feature 分支中的所有提交都合并到 master 中,就像我在 master 中所做的一样。
  3. 所有合并的提交都将合并到我的本地远程头指针之上的某处。

我最关心的是第 3 项,何时需要以便我可以安全地推送更改。如果合并的提交与 head 之前的提交交织在一起,那么我将在推送时遇到问题,请参阅我遇到的相关问题:.

我已阅读以下内容:

我想我需要做的是:

git checkout master
git pull --rebase
git checkout new_feature
git rebase master
git checkout master
git rebase new_feature
git push

我的理解是

git checkout new_feature
git rebase master

将使new_feature看起来好像是从新的当前头部分支出来的。真的吗?还有

git checkout master
git rebase new_feature

将 new_feature 放在 master 之上。那是对的吗?如果是这样,这就是我困惑的重点。如果 "git rebase master" 将 master 提交放在 new_feature 的底部,那么为什么 "git rebase new_feature" 将 new_feature 提交放在 master 的顶部,即为什么它不做相反的事情?

在 new_feature 分支上 运行 git rebase master 之后,就没有必要在 master 分支上 运行 git rebase new_feature 了。在 new_feature 分支上 运行 git rebase master 之后,您可以将 new_feature 合并到 master - 这将是一个快速合并,不会引入合并提交。

git rebase new-feature 没有在 master 之上播放所有新功能提交的原因是因为 git 认识到 master 已经在新功能的基础上 - 我们执行了该步骤git rebase master - 它只会重新定位自己。所以它只是快进到新功能。

此外,您不必担心推送位于 remote/master 提示下方的提交——如果您尝试,远程将拒绝您的推送(除非您提供 -f 选项,不要't).而且,如果您的本地 master 正在跟踪您的远程 master,git status 将判断您的本地分支是否与您的远程分支不同。

回答

这是一个您可以使用的工作流程,它可以完成您需要的工作。

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)

说明

(1) git pull --rebase 将首先获取 origin/master,然后在其上重放本地 master。请注意,在示例日志中,您的本地提交位于 "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.

您现在可以 checkout 并在您的 new_feature 分支上工作一段时间。完成后...

(2) git rebase master 将在 master 之上重播 new_feature。同样,您的本地提交仍然在您的 "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.

rebase 命令只是把 new_feature 放在 master 前面,要对齐它们你需要 运行...

(3) git merge new_feature,这将进行快进合并。现在 HEADnew_featuremaster 都指向同一个提交。

> 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) 之后,就可以放心删除new_feature分支了。推送前的最终日志将如下所示:

> 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.