带有重命名文件的Git rebase

时间:2017-03-02 23:49:47

标签: git merge rebase

我有一个重命名许多文件的分支,我试图将其重新绑定到原始文件已被修改的master(最好不要将其转换为手动冲突解决方案)恶梦)。

情况

  1. 我已经在我的本地typescript分支中将JavaScript项目移植到TypeScript。所有.js文件现已成为.ts个文件,并且某些语法已升级。

  2. 同时,.js分支上发生了原始master文件的更改。

  3. 我想将<{strong> 我的typescript分支转移到master - 但是这些更改没有正确合并,因为文件重命名没有被删除已检测到 - 因此我们发生了对git认为已删除的.js文件进行更改的冲突(但实际上已将其重命名为.ts文件)。

    < / LI>

    我想我知道

    Git图:

    o-[typescript] .js files become .ts
    |
    | o-[master] changes to the .js files
    | |
    | o
    |/
    o-[root] common ancestor
    

    所以,站在root分支:

    • 我可以运行此命令查看所有重命名:git diff --name-status --find-renames=10% typescript

    • 我知道git merge命令具有相同的--find-renames功能,但我很难让它工作。

      • 更新: git merge -X find-renames=10% mybranch似乎是预期的语法。
    • 我理解git rebase 可能支持find-renames功能,但我还不清楚如何使用它。

    解决方案的想法?

    1. (不)也许来自root,我可以在检测到重命名时合并typescript(例如:git merge -X find-renames=10% typescript)。然后,root将像typescript一样,除了重命名(而不是大量删除/添加)。

      • 从那里开始,我希望我能git rebase master,并且重命名已经到位,操作将顺利进行并将编辑内容放入正确的文件中。
        • 更新:我尝试了这一点,但我后续的改版并没有比以前更好。
    2. (是的)我想也许需要使用find-renames选项来执行rebase本身..我正在研究这个......

      • git rebase -X find-renames=10% master - nope
      • git rebase -X --find-renames=10% master - nope
      • git rebase --find-renames=10% master - nope
      • git rebase -X recursive --find-renames=10% master - nope
      • git rebase --merge -X find-renames=10% master - nope
      • git rebase --strategy-option="rename-threshold=10" master - 这是门票!它有效!
    3. (不)也许我需要以不同的方式看问题?也许我应该从master开始,然后将typescript与重命名检测进行某种压缩合并(而不是任何类型的rebase?)

      • 我不需要typescript分支历史记录,它会被压缩到一个胖子提交以供审查..
      • 更新:当我尝试使用此策略时,Git似乎停止工作。当我站在root分支时,我可以运行git merge -X find-renames=10 typescript - - 它快速转发到typescript ..(不是我希望的那样,我希望有一个新的提交,它重命名而不是添加/删除..)
        • 当我站在master分支机构中,并运行 完全相同的命令 时,git会告诉我:{{1} } ...
        • 现在,这让我感到困扰,因为我实际上并没有输入所引用的内容(我确实包含了空格),而且对我来说唯一不同的是我目前所处的分支 - 如果选项是&#34;未知&#34;,那么为什么在另一个分支中工作
        • 无论如何,这令人毛骨悚然,似乎让这种方法变成了死胡同。

3 个答案:

答案 0 :(得分:17)

您可以在检测重命名时修改分支:

createCompatibleDestImage

编辑: 自Git 2.8.0以来,术语“重命名阈值”&#39;已被弃用,以支持“重新命名&#39;。

目前我正在使用Git 2.7.4,因此我只能实际验证上述命令在我的情况下有效 - 您可能需要使用术语&#39; find-renames& #39;如果上述命令在您的新版本的Git中不起作用...

在此示例中,

  • 当前分支重新定位到git rebase --strategy-option="rename-threshold=10" master
  • 指定了master的重命名阈值
  • 10%对原始文件的更改将放置在新的(重命名的)文件中(而不是仅运行master)。
  • 请注意与git rebase mastergit diffgit log命令中的类似重命名检测功能相比,语法有何不同

git rebase文档对于这个重命名检测方面并不是很清楚。我以为我在某个地方读过另一个命令,即术语&#34; rename-threshold&#34;虽然在这种情况下git merge似乎没有作为同义词 - 所以如果有人知道运行这个命令的更好方法,请提及:)

答案 1 :(得分:1)

除了find-rename rebase/merge strategy之外,在Git 2.29(2020年第4季度)中,用于解释音序器机器相互冲突的块的每一面的提交标签已被人类更易读。

请参见commit 7d056deElijah Newren (newren)(2020年8月12日)。
(由Junio C Hamano -- gitster --commit 6cceea1中合并,2020年8月19日)

sequencer:避免由于提交标签而导致合并机器消息混乱

签名人:伊利亚·纽伦
评论人:泰勒·布劳
代理人:Johannes Schindelin

定序器的get_message()的存在是为了为冲突对象提供良好的标签;
查看提交

  • d68565402a(“还原:在冲突块上澄清标签”,2010-03-20,Git v1.7.1-rc0)
  • bf975d379d(“选择樱桃,还原:为祖先添加标签”,2010-03-20,Git v1.7.1-rc0)
  • 043a4492b3(“序列器:内置不可恢复的因子代码”,2012年1月11日,Git v1.7.1-rc0)。
    以获得此功能的背景。

这些标签的格式如下 ... 要么 ...的父母

这些标签然后作为分支名称传递到合并机器。

但是,这些标签的格式经常也会引起混淆。

例如,如果我们在内容合并中涉及到重命名,那么它将产生如下文本:

<<<<<<<< HEAD:foo.c
  int j;
========
  int counter;
>>>>>>>> b01dface... Removed unnecessary stuff:bar.c  

或者在各种冲突消息中,它会使阅读变得非常困难:

CONFLICT (rename/delete): foo.c deleted in b01dface... Removed
unnecessary stuff and renamed in HEAD.  Version HEAD of foo.c left
in tree.  

CONFLICT (file location): dir1/foo.c added in b01dface... Removed
unnecessary stuff inside a directory that was renamed in HEAD,
suggesting it should perhaps be moved to dir2/foo.c.  

进行较小的更改以删除省略号,并在提交摘要周围添加括号;这使得所有三个示例都更容易阅读:

<<<<<<<< HEAD:foo.c
  int j;
========
  int counter;
>>>>>>>> b01dface (Removed unnecessary stuff):bar.c  

CONFLICT (rename/delete): foo.c deleted in b01dface (Removed
unnecessary stuff) and renamed in HEAD.  Version HEAD of foo.c left
in tree.  

CONFLICT (file location): dir1/foo.c added in b01dface (Removed
unnecessary stuff) inside a directory that was renamed in HEAD,
suggesting it should perhaps be moved to dir2/foo.c.

答案 2 :(得分:-1)

首先重做master分支中重命名的文件可能会有所帮助。如果需要,这似乎是一项相当机械的任务。

然后,在此基础上重新定位typescript分支可能相当容易,因为已经存在共同点。有条件的typescript的一些提交最终(几乎)为空,因为它们的更改已包含在master中。

出于这个原因,您可能需要考虑将typescript合并到master,以保持原始.js.ts转换历史记录不变。