自上次合并以来的 Git 修订范围,包括该合并



假设我在 Git 中有以下情况。

基本上,有人从主分支出来,然后合并到他们的分支(一次或多次)。

*   <- 'master'
| * <- 'topic'
| *
|/|
* |
| * <- 'topic' created
|/
*

我可以使用 Git 修订范围来遵守自"master"和"主题"之间的最后一个共同祖先以来对"主题"的提交。在这种情况下,它将是"主题"和"主题~"。

背景:我正在尝试在"master"上创建一个新的(非合并)提交,其中包含"主题"的所有更改,同时避免解决已经在"主题"上解决的冲突。我在考虑"格式补丁",然后是"am",或者可能是带有"--no-commit"的"樱桃选择"。由于合并提交,变基给我带来了挑战。

谢谢

在某些情况下,答案是你不能那样做。 这不是一个,但用 gitrevisions 语法拼写出来是很棘手的。

它也可能无助于您的最终目标:

我正在尝试在"主"上创建一个新的(非合并)提交,其中包含"主题"中的所有更改......

您可能希望:

git checkout master
git merge --squash topic

之后,对名称topic唯一明智的做法是完全删除它。

继续,到 gitrevisions

让我们为图形中的每个提交分配字母名称。 这是您的图形绘图 - 请注意,我假设这是修剪或手动编辑git log --graph --oneline输出:

F   <- 'master'
| E <- 'topic'
| D
|/|
C |
| B <- 'topic' created
|/
A

我只是简单地用一个字母替换了每个*,以便我们可以计算每个提交。

只能从master访问提交F。 它有一个单亲父母,C. 提交E只能从topic访问,并且具有单个父D。 提交D只能从主题访问,但是是与父CB的合并提交,C是第一个父级。1提交C本身是一个普通的单父提交,具有父A;提交B是具有父A的普通单父提交;提交A是根本没有父级的根提交。

该图可能具有误导性,因为名称topic很可能是在master标识提交A时创建的,当时topic命名为提交A。 所以"topic创建"应该指向A,尽管A显然是从master尖直接击落的:我们从提交F开始,去提交C,然后去提交A

选择提交EDB很容易:这只是topic ^master,你可以拼写为master..topic。 按名称master选择的提交集是{F, C, A}。 按名称topic选择的提交集{E, D, C, B, A}。 从第二个集合中减去(或排除)第一个集合会产生集合{E, D, B}

要选择提交ED,请考虑,例如:

git rev-list topic ^topic^^@

也就是说,我们希望修订可以从topic访问 - 正如我们已经看到的{E, D, C, B, A}- 但不包括合并提交D的所有父级。 语法rev^@的意思正是给定修订版的所有父级,因此^rev^@表示排除给定修订版的所有父级。 在这种情况下,rev部分是topic^,所以我们最终得到^topic^^@. 这些帽子或插入^符号中的每一个都在做不同的事情:

  • 领先的^意味着不是;
  • 紧跟在主题之后的^,在topic^中,表示第一个父项;和
  • 最后的^@序列表示所有父项

请注意,您也可以拼写此^topic~1^@^topic~^@

要选择提交EB但完全排除D,您可以使用以下事实:当git rev-list遍历图形时,它允许您根据某些条件从其输出中排除提交。 因为我们知道master..topicEDB,我们可以使用该语法,但添加--no-merges。 并非每个命令都支持此语法,但git rev-list支持,您可以使用git rev-list本身生成原始哈希 ID 列表,然后可以将其提供给大多数 Git 命令。

最后,考虑简单地按名称或相对说明符列出所需的每个提交,并添加--no-walk

git rev-list --no-walk topic topic~2

例如,表示提交ECtopic本身意味着提交E。 波浪号和数字后缀向后计数一定数量的第一个步骤。E的第一个也是唯一的父母是DD有两个父母。D的第一个父级是CD第二个父级是B,所以topic^^topic~2表示提交C

要按相对名称选择B,我们需要E的第一个父级的第二个父级,所以topic^^2也可以解决问题。 也就是说,topic^——或者如果我们愿意,topic^1topic~topic~1——最初选择提交D,但添加后缀^2会立即移动到D第二个父级,即B

(如果父项是正常的顺序——这样D的第一个父级是B的,第二个父级是C——我们将使用不同的相对名称。

在所有这些情况下,--no-walk意味着我们的每个选择器都不应该选择该提交及其祖先,而应该只选择该提交。


1这是不寻常的:通常C会是第二个父母。git log --graph --oneline将这种第二父母性描绘为:

F   <- 'master'
| E <- 'topic'
| D
| |
| |/
|/|
C |
| B <- 'topic' created
|/
A

也就是说,git log --graph总是将第一个父项放在左边,其他父项放在右边,即使这意味着它必须在随后的行中立即向左重新转移。

最新更新