GIT:如何强制合并提交到祖先
在GIT中,我有两个分支和两个提交:
A(master)---B(branch "topic")
- 分支“master”的HEAD是提交A
- 分支“topic”的HEAD是提交B
- 提交A是提交B的父级
我想创建一个合并提交C在“主题”分支中(它将以 A 和 B 作为父级)。 (我知道这看起来很奇怪,并且合并提交将为空。)
A(master)---B---C (branch "topic")
\-------------/
我设法以过于复杂的方式创建此合并提交(见下文)。有没有更简单的方法来创建此合并提交?
感谢您的回答!
初始状态:
$ git init plop
Initialized empty Git repository in /tmp/plop/.git/
$ cd plop/
$ git commit -m "Initial commit (commit A)" --allow-empty
[master (root-commit) a687d4e] Initial commit (commit A)
$ git checkout -b topic
Switched to a new branch 'topic'
$ git commit -m "Some work on my topic branch (commit B)" --allow-empty
[topic d4d1c71] Some work on my topic branch (commit B)
$ #OK, we now reached the initial state
一些尝试:
$ git merge master #Does not work
Already up-to-date.
$ git merge --no-ff -s ours master #Does not work
Already up-to-date.
是否有更简单的方法来实现以下目标?
$ #Let's try another way (too complex!)
$ git checkout master
Switched to branch 'master'
$ git merge --no-ff topic
Already up-to-date!
Merge made by recursive.
$ git checkout topic
Switched to branch 'topic'
$ git merge master
Updating d4d1c71..641e7ae
Fast-forward
$ git checkout master
Switched to branch 'master'
$ git reset --hard HEAD^1
HEAD is now at a687d4e Initial commit
$ git checkout topic
Switched to branch 'topic'
$ git log #This is what I wanted to reach
commit 641e7aeb614d9b49796e8f11abd3a0290ac08b40
Merge: a687d4e d4d1c71
Author: xxx <yyy.zzz>
Date: Sat Jul 23 12:52:41 2011 +0200
Merge branch 'topic'
commit d4d1c71c87b94335c8852ab7675cbb663965ef7d
Author: xxx <yyy.zzz>
Date: Sat Jul 23 12:50:11 2011 +0200
Some work on my topic branch (commit B)
commit a687d4eb88b9f6d661122a5766dd632dd462fbaa
Author: xxx <yyy.zzz>
Date: Sat Jul 23 12:49:52 2011 +0200
Initial commit (commit A)
In GIT, I have two branches and two commits:
A(master)---B(branch "topic")
- the HEAD of the branch 'master' is commit A
- the HEAD of the branch 'topic' is commit B
- commit A is the parent of commit B
I would like to create a merge commit C in the "topic" branch (it would have A and B as parents). (I know that this seems odd, and that the merge commit would be empty.)
A(master)---B---C (branch "topic")
\-------------/
I managed to create this merge commit in a too complex way (see below). Is there any easier way to create this merge commit?
Thanks for your answers!
Initial state:
$ git init plop
Initialized empty Git repository in /tmp/plop/.git/
$ cd plop/
$ git commit -m "Initial commit (commit A)" --allow-empty
[master (root-commit) a687d4e] Initial commit (commit A)
$ git checkout -b topic
Switched to a new branch 'topic'
$ git commit -m "Some work on my topic branch (commit B)" --allow-empty
[topic d4d1c71] Some work on my topic branch (commit B)
$ #OK, we now reached the initial state
Some tries:
$ git merge master #Does not work
Already up-to-date.
$ git merge --no-ff -s ours master #Does not work
Already up-to-date.
Is there an easier way to achieve the following?
$ #Let's try another way (too complex!)
$ git checkout master
Switched to branch 'master'
$ git merge --no-ff topic
Already up-to-date!
Merge made by recursive.
$ git checkout topic
Switched to branch 'topic'
$ git merge master
Updating d4d1c71..641e7ae
Fast-forward
$ git checkout master
Switched to branch 'master'
$ git reset --hard HEAD^1
HEAD is now at a687d4e Initial commit
$ git checkout topic
Switched to branch 'topic'
$ git log #This is what I wanted to reach
commit 641e7aeb614d9b49796e8f11abd3a0290ac08b40
Merge: a687d4e d4d1c71
Author: xxx <yyy.zzz>
Date: Sat Jul 23 12:52:41 2011 +0200
Merge branch 'topic'
commit d4d1c71c87b94335c8852ab7675cbb663965ef7d
Author: xxx <yyy.zzz>
Date: Sat Jul 23 12:50:11 2011 +0200
Some work on my topic branch (commit B)
commit a687d4eb88b9f6d661122a5766dd632dd462fbaa
Author: xxx <yyy.zzz>
Date: Sat Jul 23 12:49:52 2011 +0200
Initial commit (commit A)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
UPD:更干净的方法来做同样的事情,而不直接弄乱 sha1:
或者甚至是一行命令:
有关正在做什么的详细信息 - 阅读整个答案:)
我完全同意其他人的观点对我来说没有意义,但如果你真的想要它 - 可以使用低级管道命令,如下所述。
首先,你应该知道你的父提交的 sha1。我想 B 有评论“从主题更改”,A 有评论“从主版本更改”,我们目前位于 B(主题分支)。
那么你应该知道提交B的具体树对象的sha1:
所以它是
867f31c455a371756ec353b54d755f51d98d62c4
。最后你应该执行git-commit -tree
命令:请注意,我使用了管道重定向,因为
git-commit-tree
从stdin
流获取提交注释。第一个参数是我们通过 git cat-file 获得的树的 sha1,另外两个参数是我们通过 git log 获得的提交的 sha1。命令的输出是新创建的合并提交的 sha1。现在您想要快进主题分支:
仅此而已。你有你想要的了。
UPD: Cleaner way to do same thing without messing with sha1 directly:
Or even one-line command:
For details of what that's doing - read entire answer :)
I'm totally agree with others in that it has no sense for me, but if you really want it - it is possible with low-level plumbing commands as described below.
First of all, you should know sha1 of your parent commits. I suppose B has comment 'change from topic', A has comment 'change from master' and we're currently at B (topic branch).
Then you should know sha1 of concrete tree object of commit B:
So it is
867f31c455a371756ec353b54d755f51d98d62c4
. And finally you should executegit-commit-tree
command:Note that I used pipeline redirection as
git-commit-tree
takes commit comment fromstdin
stream. First param is tree's sha1 we got withgit cat-file
and two others are commits' sha1 we got withgit log
.Output from command is the sha1 of newly created merge commit. Now you want to fast-forward topic branch to it:
That's all. You have what you wanted.
反过来合并应该可以:
Merging the other way around should work:
仅当
master
和topic
之间存在差异(如果它们存在分歧)时,进行合并提交才有意义。在你的情况下,没有什么可以合并 -topic
已经拥有master
的所有提交,因此 git 不允许你创建不执行任何操作的合并。如果您在
master
中有一个提交,但不在topic
中,它就可以正常工作:导致...
It only makes sense to make a merge commit if there's a difference between
master
andtopic
- if they have diverged. In your case, there's nothing to merge -topic
already has all ofmaster
's commits, so git won't allow you to create a merge that does nothing.It works fine if you have a commit in
master
that's not intopic
:Resulting in...
现在您位于主题分支上,并且由于它是 master 的直接后代,因此与 master 合并没有任何意义,因为 topic 包含 master 的所有更改。然而,master 没有对主题进行任何更改。
如果您签出 master,然后将主题合并到 master,master 应该快进并更新其 HEAD。
Right now you're on the topic branch, and since it's a direct descendant of master, merging with master makes no sense as topic contains all the changes master has. However, master has none of the changes topic has.
If you checkout master and then merge topic in to master, master should fast forward and update its HEAD.
这个问题没有官方解决方案,有一个解决方法。检查
master
开启的提交,以便处于分离 HEAD 状态。然后提交一个空提交。然后检查您的topic
分支并合并到该空提交中。There is no official solution to this problem, there is a workaround. Check out the commit that
master
is on, so that you are in detached HEAD state. Then commit an empty commit. Then check out yourtopic
branch and merge in that empty commit.