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:删除我想保留的文件!的主要内容,如果未能解决你的问题,请参考以下文章

git有merge时如何删除分支

git之merge操作,删除项目相关配置文件实操

git分支的创建与合并

「git」如何删除github上的文件但保留在本地

从存储库中删除文件但将其保留在本地

git(五 合并提交命令)