git逐个提交重定基

rqdpfwrv  于 2023-03-16  发布在  Git
关注(0)|答案(3)|浏览(138)

我有一个包含10个提交的分支。现在master更改了,我想将分支重定基到新master的HEAD。然而,一些新master提交甚至会使分支的第一个提交无法编译(没有合并冲突)。如果最终所有提交都无法编译,那么重定分支的基对我来说似乎毫无意义。
我想做的是告诉get“执行一个rebase,但是在我的分支的每个提交的rebase之后等待”,这样,我可以检测代码在每次提交之后是否仍然编译,使其编译(如果需要),然后提交并继续。
这是可能的吗?有没有其他的方法可以替代干净的变基,这样每次提交仍然可以编译?

7gcisfzg

7gcisfzg1#

是的,这是可能的。
最简单的方法可能是使用git rebase -i并将每个pick更改为edit。在Git完成每个选择操作后,它将返回到命令行。现在您可以尝试构建(并运行测试)并在出现故障时修复它。一旦一切正常,根据需要运行git add -ugit commit --amend,然后git rebase --continue以按顺序应用下一提交。
在你熟悉了这个方法之后(不要马上开始!),如果你的Git支持的话,也可以考虑使用--exec

**注意:**如果要复制的提交--不管它被标记为pick还是edit--有合并冲突,git rebase都会因合并冲突而停止。即使你将它标记为edit,Git在解决冲突后也不会 * 再次 * 停止,所以如果你既要解决某个问题又要修改某个东西,你应该在这里同时完成这两件事(不要使用git commit --amend,因为你仍然在做 * 第一个 * 副本)。

详细信息,以防您感兴趣/好奇

Git实际上不可能修改任何已存在的提交,因为每个提交的真实名称--它的哈希ID--是该提交所有 * 内容 * 的加密校验和,包括您作为作者/提交者的姓名、时间戳,当然还有快照附带的所有源代码。
然而,Git可以很容易地复制一个commit-well,只要它是一个普通的非合并提交,并且只有一个父提交。给定一个哈希ID为 H 的提交,Git可以将 H(快照)转换为针对 H 的父提交的修改集。它提取父快照,然后提取提交快照,以及它们之间的任何不同(git diff <parent-of-H> <H>),这就是 * 改变 * 的内容。然后可以将这些相同的改变应用到某个 * 其他 * 提交,通过 checkout 该 * 其他 * 提交,然后提交结果。也就是说,如果我们有两个分支branch1branch2,我们可以检查第二个分支的tip提交并创建一个新的临时分支:

...--G--H--I--J   <-- branch1
      \
       K--L   <-- branch2, temp (HEAD)

然后我们把提交H转换成一个变更集,把这个变更集应用到提交L上,并创建一个新的提交,它有一个新的不同的哈希ID。这个新的提交非常像H,我们称之为H',以便于说明:

...--G--H--I--J   <-- branch1
      \
       K--L   <-- branch2
           \
            H'  <-- temp (HEAD)

这个复制操作是一个git cherry-pick(从技术上讲,每个选择操作都是一个完整的三向合并,而不仅仅是应用一个更改集风格的补丁,但是我们不需要担心这个问题,除非和直到各种复杂情况发生。)
如果我们对branch1上的所有提交 * 重复 * 挑选过程,我们会得到:

...--G--H--I--J   <-- branch1
      \
       K--L   <-- branch2
           \
            H'-I'-J'  <-- temp (HEAD)

如果我们现在将标签branch1J上“剥离”,并将其附加到J'上,从而完全丢弃临时名称,我们最终得到:

...--G--H--I--J   [abandoned]
      \
       K--L   <-- branch2
           \
            H'-I'-J'  <-- branch1 (HEAD)

因此,重定基实际上是一系列的挑选操作。* 交互式 * 重定基明确了这一点:每个提交散列ID变成脚本中的pick命令。
pick更改为edit告诉Git,在完成每个挑选步骤后,它应该停止并返回到命令行。(注意Git * 也 * 停止并返回到命令行,这都是自己完成的,如果存在合并冲突)运行git rebase --continue命令Git查询所留下的控制文件-这些提交是由Git内部调用的 sequencer 来管理的--查看还有哪些提交需要处理。因此,如果你将每个提交都标记为“待编辑”,Git会在将H复制到H'后停止,这样你就得到了:

...--G--H--I--J   <-- branch1
      \
       K--L   <-- branch2
           \
            H'  <-- HEAD

(我已经更新了绘图,以依赖于Git真正完成此操作的方式:Git并没有试图创造一个临时分支名,而是使用“detached HEAD”模式来复制分支。
此时,如果你做了修改并运行git add -u && git commit --amend,Git会再次提交一个新的提交--我们称之为H-prime-prime或H"--它的父提交和H'的父提交相同:

...--G--H--I--J   <-- branch1
      \
       K--L   <-- branch2
          |\
          | H'  [abandoned]
           \
            H"  <-- HEAD

当你运行git rebase --continue时,Git会选择提交II',并将其附加到H",然后--因为你说的是“edit”--再次停止:

...--G--H--I--J   <-- branch1
      \
       K--L   <-- branch2
          |\
          | H'  [abandoned]
           \
            H"-I'  <-- HEAD

等等。

piah890a

piah890a2#

当你在执行交互式变基时,edit选项允许你在提交时暂停,使用git commit --amend添加任何修改,然后使用git rebase --continue继续下一个提交。

wooyq4lh

wooyq4lh3#

在这种情况下,我建议使用cherry-pick ing,而不是rebase
例如,如果要对main上的分支feature执行rebase操作:
1.在main上创建分支feature2,并在其上创建checkout

  1. cherry-pickfeature提交到feature2上,一个接一个
    1.在featurereset上安装checkout,然后将其(--keep--hard)安装到feature2上。
    1.删除feature2

相关问题