基于「=10=」
Rebase onto Rebase/Squash
这是我遇到的常见情况,我正在寻找一个干净的解决方案。
- 在 git 分支上做一些工作 (
my-first-work
)
- 推送到 github
- 在工作
my-first-work
的基础上开始一个新的分支(some-further-work
)
未指定的时间量
- 批准者将
my-first-work
变基或压缩到 master
- 这会创建新的提交,git 不会将其视为等同于我所基于的内容,即使最终结果相同(即
master
的头部与my-first-work
) 的头
- 我 运行
git rebase master
将 some-further-work
移动到 master
- 我现在所基于的来自
my-first-work
的提交都与已经发生的冲突 squash/merged
目前,我通过使用 git rebase -i master
然后删除所有提交直到 my-first-work
的头部来解决这个问题。这会在 master
.
之上干净地重播额外的提交
是否有更清洁的解决方案?有没有办法让 git 在 rebase/squash(如 4)发生时自动识别?
Cleaner 在旁观者/工人的眼中(或手上?),但您可以使用 git rebase --onto
分离出 哪些提交从 复制 副本 .
记住 git rebase
表示:1 我有一个线性提交链,如图 1 所示,我想将其复制到一个新的线性提交链,如图 2 所示。复制完成后,我希望我的分支名称指向最后复制的提交。原来的A-B-C
链即使还在也已经没用了
[drawing 1]
...--o--*--o <-- upstream/master
\
A--B--C <-- topic
[drawing 2]
...--o--*--o <-- upstream/master
\
A'-B'-C' <-- topic
原始提交和副本之间的区别在于,原始提交基于提交*
,是之前upstream/master
的提示。副本基于 upstream/master
的(新)提示。短语 based on 这里有两个字面意思: parent of commit A
是 commit *
但是 parent of commit A'
是后面的提交,snapshot in commit A
是*
-plus-在 快照 提交 A'
中将 相同的 更改添加到 之后的 提交。
由于我们使用闪亮的新提交 A'
(具有不同的哈希值)来支持旧的沉闷 A
,因此我们需要将 B
复制到 B'
,C
到C'
,完成后我们需要我们的名字topic
不指向C
,而是指向最后复制的提交,C'
.
普通旧 git rebase
正是这样做的。我们说:
git checkout topic; git rebase upstream/master
这告诉 Git:
- 枚举从
C
开始并向后计算的所有提交。 即 C
然后 B
然后 A
然后 *
然后是 *
. 之前的所有内容
- 枚举从
upstream/master
开始并向后工作的所有提交。 那是第二个 o
,然后是 *
,然后是 *
.
- 将第二个列表中的所有内容从第一个列表中敲出。这样就敲了out
*
和所有较早的提交。第二个 o
不在第一个列表中,但没关系:如果它 在 中,我们会把它淘汰,但事实并非如此,所以我们什么都不做。我们的列表现在变为 C
、B
和 A
。
- 反转列表以将其放入正确的顺序,然后一次一个,将每个提交复制到新位置。新位置从
upstream/master
指向的提交开始。 所以这会将 A
复制到 A'
,B
到 B'
,并且 C
到 C'
.
- 将当前分支名称
topic
从其先前的位置剥离,并像往常一样将其粘贴到新的提交链上。 所以这使得 topic
指向 C'
而不是 C
.
不过,在您的新案例中,您有:
...--o--* <-- upstream/master
\
A--B--C <-- feature1
\
D--E--F--G <-- feature2
他们在他们的上游,没有拿走你的 A-B-C
链。相反,他们做出了自己不同的 ABC
壁球提交。您从上游存储库中获取了它,所以您现在拥有:
...--o--*--ABC <-- upstream/master
\
A--B--C <-- feature1
\
D--E--F--G <-- feature2
如果你只是 运行 git checkout feature2; git rebase upstream/master
,你的 Git 将枚举提交 G-F-E-D-C-B-A-*-...
,枚举 ABC-*-...
,从第一个中减去第二个,然后是留下复制 G-F-E-D-C-B-A
链的说明。
更高级的 rebase 命令是:
git checkout feature2
git rebase --onto upstream/master feature1
这样做是将 target 参数(Git 将开始复制的地方)与 limit 分开争论。 target 现在是 upstream/master
(Git 文档将其称为 onto 参数)。 限制 参数现在是 feature1
。如果您愿意,可以使用提交 C
的原始哈希 ID。 Git 只需要知道:我从哪里开始淘汰这些提交枚举?(令人困惑的是,Git 文档将其称为 上游 参数。)
如您所见,这现在删除了 C-B-A-*
提交,而不仅仅是 *
提交,因此在复制之后,您有:
D'-E'-F'-G' [in progress]
/
...--o--*--ABC <-- upstream/master
\
A--B--C <-- feature1
\
D--E--F--G <-- feature2
现在 Git 可以将标签 feature2
撕下 G
并贴在 G2
上。
1从技术上讲,git rebase
的功能还有很多,尤其是现在新增了 --rebase-merges
选项。这个我有一个线性提交链仍然是它的主要用途,不过
作为一个很好的奖励,rebase 通常可以判断他们是否已经将您的 A-B-C
链复制到他们自己的 A'-B'-C'
链中。但这只是 通常 。 Rebase 可以 永远不会 告诉他们已经拿走了你的 A-B-C
并将其压缩成他们自己的 ABC
,所以对于这种情况你只能使用 --onto
.
这是我遇到的常见情况,我正在寻找一个干净的解决方案。
- 在 git 分支上做一些工作 (
my-first-work
) - 推送到 github
- 在工作
my-first-work
的基础上开始一个新的分支(
some-further-work
)
未指定的时间量
- 批准者将
my-first-work
变基或压缩到master
- 这会创建新的提交,git 不会将其视为等同于我所基于的内容,即使最终结果相同(即
master
的头部与my-first-work
) 的头
- 我 运行
git rebase master
将some-further-work
移动到master
- 我现在所基于的来自
my-first-work
的提交都与已经发生的冲突 squash/merged
目前,我通过使用 git rebase -i master
然后删除所有提交直到 my-first-work
的头部来解决这个问题。这会在 master
.
是否有更清洁的解决方案?有没有办法让 git 在 rebase/squash(如 4)发生时自动识别?
Cleaner 在旁观者/工人的眼中(或手上?),但您可以使用 git rebase --onto
分离出 哪些提交从 复制 副本 .
记住 git rebase
表示:1 我有一个线性提交链,如图 1 所示,我想将其复制到一个新的线性提交链,如图 2 所示。复制完成后,我希望我的分支名称指向最后复制的提交。原来的A-B-C
链即使还在也已经没用了
[drawing 1]
...--o--*--o <-- upstream/master
\
A--B--C <-- topic
[drawing 2]
...--o--*--o <-- upstream/master
\
A'-B'-C' <-- topic
原始提交和副本之间的区别在于,原始提交基于提交*
,是之前upstream/master
的提示。副本基于 upstream/master
的(新)提示。短语 based on 这里有两个字面意思: parent of commit A
是 commit *
但是 parent of commit A'
是后面的提交,snapshot in commit A
是*
-plus-在 快照 提交 A'
中将 相同的 更改添加到 之后的 提交。
由于我们使用闪亮的新提交 A'
(具有不同的哈希值)来支持旧的沉闷 A
,因此我们需要将 B
复制到 B'
,C
到C'
,完成后我们需要我们的名字topic
不指向C
,而是指向最后复制的提交,C'
.
普通旧 git rebase
正是这样做的。我们说:
git checkout topic; git rebase upstream/master
这告诉 Git:
- 枚举从
C
开始并向后计算的所有提交。 即C
然后B
然后A
然后*
然后是*
. 之前的所有内容
- 枚举从
upstream/master
开始并向后工作的所有提交。 那是第二个o
,然后是*
,然后是*
. - 将第二个列表中的所有内容从第一个列表中敲出。这样就敲了out
*
和所有较早的提交。第二个o
不在第一个列表中,但没关系:如果它 在 中,我们会把它淘汰,但事实并非如此,所以我们什么都不做。我们的列表现在变为C
、B
和A
。 - 反转列表以将其放入正确的顺序,然后一次一个,将每个提交复制到新位置。新位置从
upstream/master
指向的提交开始。 所以这会将A
复制到A'
,B
到B'
,并且C
到C'
. - 将当前分支名称
topic
从其先前的位置剥离,并像往常一样将其粘贴到新的提交链上。 所以这使得topic
指向C'
而不是C
.
不过,在您的新案例中,您有:
...--o--* <-- upstream/master
\
A--B--C <-- feature1
\
D--E--F--G <-- feature2
他们在他们的上游,没有拿走你的 A-B-C
链。相反,他们做出了自己不同的 ABC
壁球提交。您从上游存储库中获取了它,所以您现在拥有:
...--o--*--ABC <-- upstream/master
\
A--B--C <-- feature1
\
D--E--F--G <-- feature2
如果你只是 运行 git checkout feature2; git rebase upstream/master
,你的 Git 将枚举提交 G-F-E-D-C-B-A-*-...
,枚举 ABC-*-...
,从第一个中减去第二个,然后是留下复制 G-F-E-D-C-B-A
链的说明。
更高级的 rebase 命令是:
git checkout feature2
git rebase --onto upstream/master feature1
这样做是将 target 参数(Git 将开始复制的地方)与 limit 分开争论。 target 现在是 upstream/master
(Git 文档将其称为 onto 参数)。 限制 参数现在是 feature1
。如果您愿意,可以使用提交 C
的原始哈希 ID。 Git 只需要知道:我从哪里开始淘汰这些提交枚举?(令人困惑的是,Git 文档将其称为 上游 参数。)
如您所见,这现在删除了 C-B-A-*
提交,而不仅仅是 *
提交,因此在复制之后,您有:
D'-E'-F'-G' [in progress]
/
...--o--*--ABC <-- upstream/master
\
A--B--C <-- feature1
\
D--E--F--G <-- feature2
现在 Git 可以将标签 feature2
撕下 G
并贴在 G2
上。
1从技术上讲,git rebase
的功能还有很多,尤其是现在新增了 --rebase-merges
选项。这个我有一个线性提交链仍然是它的主要用途,不过
作为一个很好的奖励,rebase 通常可以判断他们是否已经将您的 A-B-C
链复制到他们自己的 A'-B'-C'
链中。但这只是 通常 。 Rebase 可以 永远不会 告诉他们已经拿走了你的 A-B-C
并将其压缩成他们自己的 ABC
,所以对于这种情况你只能使用 --onto
.