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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/28550602/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-19 10:46:20  来源:igfitidea点击:

git: Merge Branches but Keep Commit History

gitversion-controlbranchhistoryrebase

提问by Samuel

In my git workflow we have one main repository and one branch, master. Everyone pulls from remote master and everyone pushes to remote master. I want to work in my own branch while I prepare a feature. So far my history is something like this:

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

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

Now I want to merge the branch and here's what I need:

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

  1. No merge commits in my local master branch.
  2. All commits made into my new_feature branch merged into master as if I had made them in master.
  3. All merged commits to be merged somewhere on top of my local remote head pointer.
  1. 我的本地主分支中没有合并提交。
  2. 在我的 new_feature 分支中所做的所有提交都合并到 master 中,就像我在 master 中所做的一样。
  3. 所有合并的提交都将合并到我本地远程头指针之上的某处。

My biggest concern is item 3, when is needed so that I can safely push the changes. If the merged commits are intertwined with commits before head then I will have problems pushing, see related problem I had: git: Pushing Single Commits, Reordering with rebase, Duplicate Commits.

我最关心的是第 3 项,什么时候需要,以便我可以安全地推送更改。如果合并的提交在 head 之前与提交交织在一起,那么我将遇到推送问题,请参阅我遇到的相关问题:git: Pushing Single Commits, Reordering with rebase, Duplicate Comits

I've read the following:

我已阅读以下内容:

And I think I need to do:

我认为我需要这样做:

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

My understanding is that

我的理解是

git checkout new_feature
git rebase master

will make new_feature appear as if it was branched off from the new current head. Is that true? And that

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

git checkout master
git rebase new_feature

will place new_feature on top of master. Is that correct? If so, this is the main point of my confusion. If "git rebase master" places master commits at the bottom of new_feature, then why does "git rebase new_feature" place new_feature commits at the top of master, i.e. why doesn't it do the opposite?

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

回答by Shaun Luttin

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 --rebasewill first fetch origin/masterand then replay your local masteron top of it. Note in the example log that your local commits are on top of your "local remote HEAD pointer."

(1)git pull --rebase将首先获取origin/master,然后master在它上面重放您的本地。请注意示例日志中的本地提交位于“本地远程 HEAD 指针”之上。

> 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 checkoutand work on your new_featurebranch for a while. When you're done...

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

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

(2)git rebase masternew_featuremaster. 同样,您的本地提交仍位于“本地远程 HEAD 指针”之上。

> 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 rebasecommand just put new_featureahead of master, and to align them you need to run...

rebase命令只是放在new_featuremaster 之前,要对齐它们,您需要运行...

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

(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) After that, you can safely delete the new_featurebranch. Your final log before pushing will look like this:

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

回答by Dan Fischer

It's unnecessary to run git rebase new_featureon the master branch after you've run git rebase masteron the new_feature branch. After you've run git rebase masteron 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.

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

The reason why git rebase new-featureisn'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.

之所以git rebase new-feature不在 master 之上播放所有新功能提交的原因是因为 git 识别 master 已经在新功能的基础上 - 我们执行了这一步git rebase master- 并且它只会重新建立在自己的基础上。因此,它只是快进到新功能。

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 statuswill tell if your local has diverged from you remote branch.

此外,您无需担心推送驻留在远程/主提示下方的提交——如果您尝试,远程将拒绝您的推送(除非您提供 -f 选项,否则)。并且,如果您的本地 master 正在跟踪您的远程 master,git status将判断您的本地是否与您的远程分支分开。