在某些情况下,答案只是你不能这样做。这不是一个,但是用gitrevisions 语法拼出来是很棘手的。
它可能也无助于你的最终目标:
我正在尝试在“主”上创建一个新的(非合并)提交,其中包含“主题”的所有更改...
你可能想要:
git checkout master
git merge --squash topic
在此之后,与名称 topic 做的唯一明智的事情就是完全删除它。
之后,到 gitrevisions
让我们为绘图中的每个提交分配字母名称。这又是你的图表——请注意,我假设这是经过修剪或手工编辑的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 本身是一个普通的单-parent 与父 A 提交; commit B 是一个普通的单父提交,父 A;并且 commit A 是根本没有父级的根提交。
该图可能具有误导性,因为名称 topic 很可能是在名称 master 标识提交 A 时创建的,当时 topic 也 命名提交 @987654346 @。所以“topic created”应该指向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 的所有父母。语法rev^@ 的意思正是给定版本的所有父项,所以^rev^@ 表示排除给定版本的所有父项。在这种情况下,rev 部分是topic^,所以我们最终得到^topic^^@。这些帽子或插入符号^ 符号中的每一个都在做不同的事情:
- 前导
^表示不是;
-
^ 紧随主题之后,在topic^ 中,表示第一个父级;和
- 末尾的
^@ 序列表示所有的父母。
请注意,您也可以拼写此 ^topic~1^@ 或 ^topic~^@。
要选择提交 E 和 B 但完全排除 D,您可以使用以下事实:当 git rev-list 遍历图表时,它可以让您排除基于其输出的提交在某些标准上。由于我们知道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 表示提交 @987654408 @。
要通过相对名称选择B,我们需要E 的第一个父级的第二个父级,所以topic^^2 也可以做到这一点。也就是说,topic^——或者如果我们愿意,topic^1 或 topic~ 或 topic~1——最初选择提交 D,但添加后缀 ^2 后立即移动到 second D 的父级 B。
(如果父母是正常顺序——所以D的第一个父母是B,它的第二个是C——我们' d 使用不同的相对名称。)
在所有这些情况下,--no-walk 意味着我们的每个选择器不应该选择那个提交及其祖先,而应该只选择那个提交。
1这很不寻常:通常C 将是第二个父级。 git log --graph --oneline 会将这个第二父母描绘为:
F <- 'master'
| E <- 'topic'
| D
| |\
| |/
|/|
C |
| B <- 'topic' created
|/
A
也就是说,git log --graph 总是将 first 父级放在左侧,其他父级放在右侧,即使这意味着它必须在下一行中立即重新转向左侧。