当重命名文件并使用旧名称创建新文件时,什么工作流可以减轻git合并冲突?

当重命名文件并使用旧名称创建新文件时,什么工作流可以减轻git合并冲突?,git,merge,rename,git-merge,git-merge-conflict,Git,Merge,Rename,Git Merge,Git Merge Conflict,问题 我有根分支master和feature从master分支 master具有文件A 功能已将文件A移动到B并创建了一个新文件A 在master中针对文件A工作需要合并到功能分支文件B 将master合并到功能中会导致合并冲突主文件A尝试合并到功能文件A中,即使主文件A和功能A不再相关。 我如何告诉git将masterA合并到featureB 步骤重现 在控制台中: mkdir git_rename_demo cd git_rename_demo git init echo "LineB1

问题

  • 我有根分支
    master
    feature
    从master分支
  • master
    具有文件
    A
  • 功能
    已将文件
    A
    移动到
    B
    并创建了一个新文件
    A
  • master
    中针对文件
    A
    工作需要合并到
    功能
    分支文件
    B
  • master
    合并到
    功能中会导致合并冲突<代码>主文件
    A
    尝试合并到
    功能
    文件
    A
    中,即使
    主文件
    A
    功能
    A
    不再相关。 我如何告诉git将
    master
    A
    合并到
    feature
    B
  • 步骤重现

    在控制台中:

    mkdir git_rename_demo
    cd git_rename_demo
    
    git init
    
    echo "LineB1\nLineB2\nLineB3\nLineB4" > A.txt
    git add A.txt
    git commit -m "Add A"
    
    git checkout -b rename_A_to_B
    git mv A.txt B.txt
    echo "LineA1\nLineA2\nLineA3" > A.txt
    git add A.txt
    git commit -m "Moved Old A to B and Added New A"
    
    git checkout master
    echo "LineB5\nLineB5" >> A.txt
    git add A.txt
    git commit -m "Added More LineBs to A"
    
    git checkout rename_A_to_B
    git merge master
    
    场景

    我有一个
    分支和一个
    功能
    分支。
    master
    上的文件
    A
    ,包含执行“A”相关逻辑的代码

    功能
    分支上,发现文件
    A
    作为文件名没有意义,因为代码与“B”逻辑更相关。同时,编写了与
    feature
    分支中的“A”逻辑相关的新代码。为了解决这个问题,文件
    A
    被重命名为文件
    B
    ,这实际上意味着文件
    A
    中所有与“B”相关的原始逻辑都已移动到新文件
    B
    。所有新的“A”相关逻辑被添加到名为
    A
    的新文件中,有效地替换了旧的
    A
    文件

    master
    分支的工作仍在继续,在仍然存在的
    A
    文件中添加了更多的“B”逻辑。这是
    功能
    分支上已重命名为
    B
    的文件


    此时需要将
    master
    的工作合并到
    功能中,因为功能将继续与
    master
    分开开发,直到稍后的日期。
    master
    feature
    的合并会导致上述冲突。我们需要继续允许从事
    master
    工作的开发人员针对
    A
    执行与“B”相关的工作,并能够将
    A
    文件工作合并到
    功能
    分支
    B
    文件中,而无需每次手动解决冲突。

    我不确定您是否能找到自动解决方案。 但是您可以从git diff创建补丁,并在feature分支中手动更新git apply。

    TL;博士 没有真正好的方法来处理这个问题,但是您可以手动完成。见下文

    长的 不要太担心分支名称。不要担心承诺;合并基于提交,而不是分支名称。分支名称只是帮助您和Git查找特定的提交。根据定义,分支名称始终包含分支中最后一次提交的原始提交哈希ID。添加新提交包括:

  • 按名称检查分支,以便Git知道在步骤3中更新哪个分支名称。这使分支的提示提交成为当前提交。特殊名称
    HEAD
    现在附加到分支名称,因此,
    HEAD
    选择当前提交,这是分支中的最后一次(或提示)提交

  • 以通常的方式做出新的承诺。Git将创建提交,将其父级设置为当前提交。这个新的提交将获得它自己唯一的hash ID,不同于以前的每个提交,也不同于将来的每个提交

  • 此时,在进行了新提交之后,Git将新提交的哈希ID写入一个分支名称中:即
    HEAD
    所附加的分支名称。因此,现在分支名称指向分支中的最后一个(提示)提交。新的提交指向过去的提示;分支现在比提交长一个

  • 无论何时进行真正的合并(存在一些虚假的合并),都会涉及三种提交:

    • 合并基,它是其他两个提交的最佳共同祖先
    • 当前提交(或
      ),通常是分支的尖端;1及
    • 在命令行中选择的提交:通常是另一个分支的尖端
    Git自己查找合并基提交。你只要说出另一个名字就行了。如果要提前查看合并基础是哪个提交,可以运行:

    git merge-base --all other
    
    其中,
    other
    是您计划提供给
    git merge
    命令的内容,git从中选择第三个提交


    1另一个选项是,您可能处于分离头状态,其中特殊名称
    HEAD
    仅包含提交本身的原始散列ID。无论哪种方式,
    HEAD
    命名当前提交。当你在一个分支上时,它只是使用一个分支名称。但通常在运行“合并”时,您位于分支上


    简而言之,合并是如何工作的,这也是您的问题所在 想象一下一个简化的提交时间线,稍后的提交在右边,在这个时间线中,我们用单个大写字母替换提交哈希,以便更容易地讨论它们。我们可能会:

              I--J   <-- branch1 (HEAD)
             /
    ...--G--H
             \
              K--L   <-- branch2
    
    这就是您的问题所在:
    --find renames
    在第一个
    git diff
    中会发现合并基中的文件
    A
    ,在提交中可能也称为
    A
    ,现在在头部提交中称为
    B
    。所以diff会将“A在base中,B在ours中”配对并比较内容。这就是我们所改变的:内容改变了,文件名也改变了

    第二个
    git diff
    将“A在基地,A在他们的基地”配对,看看他们改变了什么。当我
    git diff --find-renames <hash-of-H> <hash-of-J>   # what we changed
    git diff --find-renames <hash-of-H> <hash-of-L>   # what they changed
    
    git show :1:F > F.LOCAL    # :1: means the merge base version
    git show :2:F > F.OURS     # :2: means our version, like `git checkout --ours`
    git show :3:F > F.THEIRS   # :3: means their version, like `git checkout --theirs`
    
    git merge other
    
    git merge-file B A.base A.other
    
    git checkout --ours A
    
    git add A