说我在Git中有以下情况。
基本上,某人已从master分支出来,然后合并到其分支(一次或多次)。
* <- 'master'
| * <- 'topic'
| *
|/|
* |
| * <- 'topic' created
|/
*
我可以使用Git修订范围来确定自“主”和“主题”之间最后一个共同祖先以来对“主题”的提交。在这种情况下,它将是“ topic”和“ topic〜”。
背景:我试图在'master'上创建一个新的(非合并)提交,其中包含'topic'的所有更改,同时避免解决在'topic'上已经解决的冲突。我在考虑“格式补丁”,然后是“ am”,或者用“ --no-commit”选择“ cherry-pick”。重新合并给我带来了挑战,因为合并提交。
谢谢
在某些情况下,答案只是您不能这样做。这不是一个,但是用gitrevisions语法拼写起来很棘手。
它可能也无助于您的最终目标:
我正在尝试在'master'上创建一个新的(非合并)提交,其中包含'topic'的所有更改...
您可能想要:
git checkout master
git merge --squash topic
此后,与名称topic
唯一明智的关系是完全删除它。
让我们为图形中的每个提交分配字母名称。这又是您的图形绘图-请注意,我假设这是经过修剪或手工编辑的git log --graph --oneline
输出:
F <- 'master'
| E <- 'topic'
| D
|/|
C |
| B <- 'topic' created
|/
A
我只是简单地用字母替换了每个*
,以便我们可以轻松了解每个提交。
提交F
仅可从master
访问。它有一个单亲,C
。提交E
仅可从topic
访问,并且具有单个父级D
。提交D
仅可从主题访问,但是与父项C
和B
合并的提交,其中C
是第一个父项。1提交C
本身是普通的单亲提交与父母A
; commit B
是具有父项A
的普通单亲提交;并提交A
是根本没有父项的根提交。
该图可能具有误导性,因为名称topic
最有可能是在名称master
标识提交A
时创建的,当时topic
also名为提交A
。因此,即使topic
显然是从A
尖端直接击落的,“创建的A
”也应指向master
:我们从提交F
开始,转到C
,然后转到提交A
。
选择提交E
,D
和B
很容易:就是topic ^master
,您可以将其拼写为master..topic
。名称为master
的提交集为{F, C, A}
。名称为topic
的提交集为{E, D, C, B, A}
。从第二组减去(或排除)第一组将生成组{E, D, B}
。
要选择提交E
和D
,请考虑例如:
git rev-list topic ^topic^^@
也就是说,我们希望可以从topic
到{E, D, C, B, A}
达到修订版本,但是已经排除了合并提交D
的所有parents。语法rev^@
的确切含义是给定修订版的所有父级,因此^rev^@
的意思是排除给定修订版的所有父级。在这种情况下,rev
部分为topic^
,因此我们以^topic^^@
结尾。这些帽子或插入号^
的每个符号都在做不同的事情:
^
表示not;^
中紧跟在主题之后的[topic^
,表示第一父级;和^@
序列表示]的所有父代。请注意,您也可以拼写此^topic~1^@
或^topic~^@
。
选择提交E
和B
,但完全排除D
,您可以使用以下事实:当git rev-list
遍历图形时,它允许您根据特定条件从其输出中exclude
master..topic
会走E
,D
和B
,所以我们可以使用该语法,但要添加--no-merges
。并非每个命令都支持此语法,但是git rev-list
可以,并且您可以使用git rev-list
本身生成原始哈希ID列表,然后可以将其提供给大多数Git命令。最后,请考虑按名称或相对说明符列出所需的每个提交,然后添加--no-walk
:
父级是git rev-list --no-walk topic topic~2
例如表示提交
E
和C
] >>。topic
本身表示提交E
。代字号和数字后缀向后计数<< first-parent >>个步骤。E
的第一个也是唯一的父母是D
,D
有两个父母。D
的first
C
,D
的second父级是B
,因此topic^^
或topic~2
表示提交C
。要通过相对名称选择B
,我们需要E
的第一个父级的第二个父级,因此topic^^2
也可以完成操作。也就是说,topic^
-或如果我们愿意,也可以选择topic^1
或topic~
或topic~1
-最初选择提交D
,但在其后添加后缀^2
会立即移至second
D
的父级,即B
。((如果父母是正常顺序,因此D
的first
父母是B
,而其second是C
,我们将使用不同的相对名称。) 在所有这些情况下,--no-walk
表示我们的每个选择器不应
选择该提交及其祖先,而仅是一次提交。1
这很不寻常:通常C
是第二个父级。 git log --graph --oneline
会将这个第二亲本绘制为:F <- 'master'
| E <- 'topic'
| D
| |\
| |/
|/|
C |
| B <- 'topic' created
|/
A
即,父项放在左边,而其他父项放在右边,即使这意味着它必须立即在下一行中重新转移到左边。git log --graph
始终将first