GIT:如何强制合并提交到祖先

时间:2011-07-24 13:48:03

标签: git merge commit

在GIT中,我有两个分支和两个提交:

 A(master)---B(branch "topic")
  • 分支'master'的HEAD是提交A
  • 分支'主题'的HEAD是提交B
  • commit A是commit B的父级

我想在“topic”分支中创建一个合并提交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)

5 个答案:

答案 0 :(得分:9)

UPD :更直接的方式做同样的事情而不直接搞乱sha1:

$ echo "merge commit" | git commit-tree topic^{tree} -p master -p topic
4201b6abae6bb06f929ea00fbc35019679d55535

$ git merge 4201b6abae6bb06f929ea00fbc35019679d55535
Updating b826a8e..4201b6a
Fast-forward

甚至是单行命令:

$ git merge $(echo "merge commit" | git commit-tree topic^{tree} -p master -p topic)

有关正在做什么的详细信息 - 请阅读完整答案:)


我完全赞同其他人,因为它对我没有任何意义,但如果你真的想要它 - 可以使用下面描述的低级管道命令。

首先,您应该知道父提交的sha1。我想B有评论'从主题改变',A有评论'从主人改变',我们现在在B(主题分支)。

$ git log --format=oneline -2
b826a8e93ac8da0de5bfb5b70d5f4e7c352a01fa change from topic
8b7653a529fb3ce964fda79bfd57e645441ad893 change from master

然后你应该知道提交B的具体树对象的sha1:

$ git cat-file -p topic
tree 867f31c455a371756ec353b54d755f51d98d62c4
parent 8b7653a529fb3ce964fda79bfd57e645441ad893
author ivan-danilov <email@gmail.com> 1311518908 +0300
committer ivan-danilov <email@gmail.com> 1311518908 +0300

change from topic

所以它是867f31c455a371756ec353b54d755f51d98d62c4。最后你应该执行git-commit-tree命令:

$ echo "merge commit" | git commit-tree 867f31c455a371756ec353b54d755f51d98d62c4 -p b826a8e93ac8da0de5bfb5b70d5f4e7c352a01fa -p 8b7653a529fb3ce964fda79bfd57e645441ad893
4201b6abae6bb06f929ea00fbc35019679d55535

请注意,我使用了管道重定向,git-commit-treestdin流获取提交注释。第一个参数是我们用git cat-file得到的树的sha1,另外两个是我们用git log得到的sha1。

命令输出是新创建的合并提交的sha1。现在你想快速转发主题分支:

$ git merge 4201b6abae6bb06f929ea00fbc35019679d55535
Updating b826a8e..4201b6a
Fast-forward

这就是全部。你有自己想要的东西。

答案 1 :(得分:2)

如果mastertopic之间存在差异,那么进行合并提交才有意义 - 如果它们有分歧的话。在你的情况下,没有什么可以合并 - topic已经拥有所有master的提交,所以git将不允许你创建一个什么都不做的合并。

如果master中的提交不在topic中,则可以正常工作:

$ git init plop
Initialized empty Git repository in C:/Temp/plop/.git/
$ cd plop
$ git commit -m "Initial commit (commit A)" --allow-empty
[master (root-commit) b6e2e91] Initial commit (commit A)
$ git commit -m "master-only commit (commit C)" --allow-empty
[master 67b491e] master-only commit (commit C)
$ git checkout HEAD~ -b topic
Switched to a new branch 'topic'
$ git commit -m "Some work on my topic branch (commit B)" --allow-empty
[topic 2251f13] Some work on my topic branch (commit B)
$ git merge master
Already up-to-date!
Merge made by recursive.

导致......

*   592ad46 Merge branch 'master' into topic
|\
| * 67b491e master-only commit (commit C)
* | 2251f13 Some work on my topic branch (commit B)
|/
* b6e2e91 Initial commit (commit A)

答案 2 :(得分:2)

合并相反的方法应该有效:

git branch tmp master    # tmp points to A
git checkout tmp
git merge --no-ff -m 'odd merge' topic    # merge B+A ==> C
git checkout topic
git reset --hard tmp     # topic now points to C
git branch -d tmp

答案 3 :(得分:0)

现在你在主题分支上,因为它是master的直接后代,与master合并没有任何意义,因为主题包含master拥有的所有更改。但是,master没有任何更改主题。

如果您签出master然后将主题合并到 master,master应该快进并更新其HEAD。

答案 4 :(得分:0)

此问题没有官方解决方案,有一种解决方法。查看master所在的提交,以便您处于分离的HEAD 状态。然后提交一个空提交。然后检查你的topic分支并合并那个空提交。

$ git checkout 9123456 # (the latest commit on master)
Note: checking out '9123456'.
You are in 'detached HEAD' state...
$ git commit --allow-empty -m 'empty commit'
[detached HEAD 9123457] empty commit
$ git checkout topic
Warning: you are leaving 1 commit behind ... 9123457 empty commit
Switched to branch 'topic'
$ git merge 9123457