git merge:删除我想保留的文件!
Posted
技术标签:
【中文标题】git merge:删除我想保留的文件!【英文标题】:git merge: Removing files I want to keep! 【发布时间】:2010-11-27 07:36:02 【问题描述】:如何在 git 中合并两个分支,同时保留一个分支中的必要文件?
合并两个分支时,如果一个文件在一个分支中被删除而不在另一个分支中,则该文件最终被删除。
例如:
创建新分支时,master 中存在文件 您从 master 中删除该文件,因为我们(还)不需要它 您在分支中进行更改以添加一项功能,该功能依赖于现有文件 您在 master 中进行错误修复(不能丢弃) 有一天你合并,文件不见了!如何复制:
用一个文件创建一个 git repo。
git init
echo "test" > test.txt
git add .
git commit -m "initial commit"
创建一个分支
git branch branchA
删除master中的文件
git rm test.txt
git commit -m "removed file from master"
在不涉及已删除文件的分支A 中进行任何更改(必须保持不变以避免冲突)
git checkout branchA
touch something.txt
git add .
git commit -m "some branch changes"
从这里,我找到合并这两个分支的任何方式,都会删除 test.txt 文件。假设我们 依赖文件 获取 branchA
,这是一个大问题。
失败的例子:
合并 1
git checkout branchA
git merge master
ls test.txt
合并2
git checkout master
git merge branchA
ls test.txt
变基 1
git checkout branchA
git rebase master
ls test.txt
【问题讨论】:
我相信您可以通过在合并之前从最新的 master 重新设置 branchA(只要它不是公开的)来解决这个问题。交互式变基将使您有机会告诉 git 您绝对想要该文件,然后合并应该顺利进行。 【参考方案1】:这是一个有趣的问题。因为您在创建BranchA
之后删除了文件,然后将master
合并到BranchA
,所以我不确定Git 是如何意识到存在冲突的。
合并失败后可以撤消,然后重新合并,但要重新添加文件:
git checkout HEAD@1 .
git merge --no-commit master
git checkout master test.txt
git add test.txt
git commit
【讨论】:
手动复制并重新添加文件将是一个很好的解决方法,但我想知道如何通过 git 做到这一点。如果 git 对这个分支/合并问题的回答是“做一个备份并自己做”,那么它几乎打败了我使用 git 的理由。 不,您不需要手动备份。您可以从 master 分支中获取文件。我更新了示例。 HEAD@1 是什么意思? 在 git merge 命令中添加选项 --no-ff 可能是个好主意。见***.com/questions/10935226/git-interactive-merge 如果删除的文件列表很大怎么办?这有点不公平。不是吗?否则我无法说服自己。自动合并应该在如此巨大的冲突中停止。即使文件中只有一个字符冲突,它也会停止,但如果所有字符都被删除,感觉很好。我错了吗?抱歉,我不明白逻辑。【参考方案2】:对于这种情况下的快速修复,“git revert”删除文件的提交。
当这种情况在未来出现时,更好的处理方法是确保新文件的创建发生在分支上。然后在合并时将其添加到 master 上,但与此同时您没有文件位于 master 中。
【讨论】:
删除文件的提交包括其他重要的更改。 git-revert 似乎不是一个选项,因为我不能丢失其他更改。 在这种情况下,最简单的方法可能是执行“git revert -n [commit]”,它会修补所有更改但不提交它们。然后使用“git checkout HEAD [filenames]”擦除你不想要的更改,即除了文件恢复之外的所有内容,然后提交。【参考方案3】:需要修改分支中的文件,这样与主干中的删除有合并冲突。
例如,如果您删除主干头文件中某项的声明(因为没有什么需要它),并将对该声明的依赖添加到某些非头文件中,则会发生完全相同的事情分支。当你合并时,由于分支不接触标题的(那部分),它只会删除声明并且事情会中断。
当您在多个地方有相互依赖且需要保持同步的东西时,合并很容易默默地引入问题。它只是合并时您必须了解和检查的事情之一。理想情况下,您使用编译时断言或其他构建时检查,可以立即显示任何失败。
【讨论】:
【参考方案4】:Casey 的示例不适用于我的案例 - 我无法从 master
签出 test.txt
,因为它不再在该分支中:
$ git checkout master test.txt
error: pathspec 'test.txt' did not match any file(s) known to git.
很高兴我可以从branchA
自己的HEAD
中提取文件:
$ git checkout branchA
$ git merge --no-commit master
$ git checkout HEAD test.txt
$ git add test.txt
$ git commit
【讨论】:
如果我有上千个文件要添加怎么办? 您可以将任何提交中的文件签出到当前分支。git checkout <commit hash or branch name> -- path/to/file
。 Git 也接受 glob 模式【参考方案5】:
我对此的解决方案是简单地修改我需要保留的文件(添加了无论如何都需要的注释)并在目标分支上提交这些更改,从而生成可以通过 git add
轻松解决的合并冲突和一个正常的提交。
我的历史是这样的。分行名称已更改以保护无辜者。
-
为要掌握的新功能创建和提交文件
意识到这一添加将比原计划涉及更多,因此,分支到 feature_branch
已从 master 中删除文件,以免破坏 RB 等的正常工作流程
时间过去了,master 上有更多提交,feature_branch 上没有提交
恢复功能上的工作,
git merge master
上 feature_branch 导致原始文件被删除(当然),git reset --hard
到合并之前
应用上述解决方案
【讨论】:
【参考方案6】:与 git 相同的问题。正在开发一个分支中的一个特性,然后我的工作决定将这个特性搁置一旁以备后用。因此,从 master 分支中删除了相关的功能文件,以允许在没有不必要文件的情况下部署应用程序......暂时。现在我的工作需要我完成旧功能,当我尝试将旧分支合并或变基到当前主分支时,它会删除我需要的文件。
快速的解决方案是:修改你需要保留在你的特性分支中的文件,添加并提交,然后与你的master合并。现在这将导致合并冲突,而不是合并时的删除模式。现在您可以保留对文件的“我们的”更改。
问题是 git 认为 HEAD 中的文件删除没有被更改,并将默认进入删除模式。具体来说:deleted in master and modified in HEAD
是你修改你需要的文件后输出的。
重现解决方案:
-
将分支重置为已删除文件的旧版本:
git reset --hard origin/old_branch
修改您需要保留的文件。不要让它们保持不变。
将你当前的master合并到特性分支中:git merge master
自动合并失败;修复冲突,然后提交结果。
-
在解决冲突时保留“我们的”更改。
git add .
和 git commit -m "fix deleted HEAD"
完成合并:git merge master
【讨论】:
【参考方案7】:您可以在提交到当前合并分支之前签出文件,而不是反向合并(user Todd 的建议):
git checkout <commit hash or branch name> -- path/to/file
例如,
git checkout 08ac9cf08f -- classify.cpp
然后你就可以推送你的分支了。
【讨论】:
以上是关于git merge:删除我想保留的文件!的主要内容,如果未能解决你的问题,请参考以下文章