git merge:删除我要保留的文件!

drf*_*oob 56 git merge branch

如何在git中合并两个分支,从分支中保留必要的文件?

合并两个分支时,如果文件在一个分支中删除而在另一个分支中没有删除,则最终删除该文件.

例如:

  • 创建新分支时,master中存在一个文件
  • 你从master中删除文件,因为我们不需要它(还)
  • 您在分支中进行更改以添加依赖于现有文件的功能
  • 你在master中修复bug(不能丢弃)
  • 你有一天合并,文件消失了!

如何再现:

  1. 用一个文件创建一个git repo.

    git init
    echo "test" > test.txt
    git add .
    git commit -m "initial commit"
    
    Run Code Online (Sandbox Code Playgroud)
  2. 创建一个分支

    git branch branchA
    
    Run Code Online (Sandbox Code Playgroud)
  3. 删除master中的文件

    git rm test.txt
    git commit -m "removed file from master"
    
    Run Code Online (Sandbox Code Playgroud)
  4. 在branchA中进行任何不接触已删除文件的更改(必须保持不变以避免冲突)

    git checkout branchA
    touch something.txt
    git add .
    git commit -m "some branch changes"
    
    Run Code Online (Sandbox Code Playgroud)

从这里,我发现合并这两个分支的任何方式都删除了test.txt文件.假设我们依靠文件branchA,这是一个很大的问题.


失败的例子:

合并1

git checkout branchA
git merge master
ls test.txt
Run Code Online (Sandbox Code Playgroud)

合并2

git checkout master
git merge branchA
ls test.txt
Run Code Online (Sandbox Code Playgroud)

Rebase 1

git checkout branchA
git rebase master
ls test.txt
Run Code Online (Sandbox Code Playgroud)

cmc*_*nty 29

这是一个有趣的问题.因为你删除后的文件BranchA被创建,然后被合并masterBranchA,我不知道混帐如何能够实现有冲突.

错误合并后,您可以撤消,然后重新合并,但添加回文件:

git checkout HEAD@{1} .
git merge --no-commit master
git checkout master test.txt
git add test.txt
git commit
Run Code Online (Sandbox Code Playgroud)

  • 手动复制和重新添加文件将是一个很好的解决方法,但我想知道如何通过git做到这一点.如果git对这个分支/合并问题的回答是"进行备份并自己动手",那么它几乎打败了我使用git的原因. (15认同)
  • 如果删除的文件列表很大怎么办?这有点不公平.不是吗?否则我无法说服自己.自动合并应该停止在如此巨大的冲突中.即使文件中只有一个字符冲突,它也会停止,但如果删除了所有字符,则感觉很好.我错了吗?对不起,我没有得到逻辑. (7认同)
  • 不,您不需要手动备份.您可以从主分支中获取该文件.我更新了这个例子. (3认同)

Phi*_*hil 6

为了在这种情况下快速修复,"git revert"删除文件的提交.

当这种情况在未来出现时,处理它的更好方法是确保在分支上发生新文件的创建.然后在合并时将其添加到master上,但在此期间您没有在master中放置文件.

  • 在这种情况下,最简单的方法可能是"git revert -n [commit]",它修补所有更改但不提交它们.然后使用"git checkout HEAD [filenames]"来擦除你不想要的更改,即除了文件恢复之外的所有内容,然后提交. (4认同)
  • 删除文件的提交包括其他重要的更改。git-revert 似乎不是一种选择,因为我不能丢失其他更改。 (2认同)

Ale*_*ean 6

Casey的示例不适用于我的情况-我无法test.txt从检出master,因为它不再位于该分支中:

$ git checkout master test.txt
error: pathspec 'test.txt' did not match any file(s) known to git.
Run Code Online (Sandbox Code Playgroud)

幸运的是,我可以将文件拉出branchA自己的文件HEAD

$ git checkout branchA
$ git merge --no-commit master
$ git checkout HEAD test.txt
$ git add test.txt
$ git commit
Run Code Online (Sandbox Code Playgroud)

  • 如果要添加数千个文件怎么办? (2认同)

Ale*_*x S 5

我的解决方案是简单地修改我需要保留的文件(添加无论如何都需要的注释)并在目标分支上提交这些更改,从而生成合并冲突,可以通过git add正常提交轻松解决。

我的历史是这样的。为了保护无辜者,分支名称已更改。

  1. 创建并提交文件以掌握新功能
  2. 意识到这个添加将比最初计划的更复杂,因此分支到 feature_branch
  3. 从 master 中删除了文件,以免扰乱 RB 等的正常工作流程
  4. 随着时间的流逝,master 上有更多提交,feature_branch 上没有提交
  5. 在 feature_branch上恢复该功能的工作git merge master会导致原始文件被删除(当然),git reset --hard直到合并之前
  6. 应用上述解决方案