git merge:删除我想保留的文件!
如何在 git 中合并两个分支,并保留分支中的必要文件?
合并两个分支时,如果一个文件在一个分支中被删除,而在另一个分支中没有被删除,则该文件最终将被删除。
例如:
- 当您创建一个新分支时,master 中存在一个文件,
- 您从 master 中删除该文件,因为我们还不需要它,
- 您在分支中进行更改以添加一个功能,这依赖于现有的文件
- 你在 master 中修复了错误(不能丢弃)
- 你有一天合并,文件就消失了!
如何重现:
使用一个文件创建一个 git 存储库。
<前><代码>git init 回显“测试”>测试.txt git 添加 . git commit -m“初始提交”创建分支
git分支branchA
删除master中的文件
git rm test.txt git commit -m“从主控中删除了文件”
在branchA中进行任何不触及已删除文件的更改(必须保持不变以避免冲突)
git checkout 分支A 触摸某物.txt git 添加 . git commit -m“一些分支更改”
从这里开始,我发现合并这两个分支的任何方法,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
How can you merge two branches in git, retaining necessary files from a branch?
When merging two branches, if a file was deleted in one branch and not in another, the file is ultimately deleted.
For example:
- A file exists in master when you make a new branch
- you remove the file from master since we don't need it (yet)
- you make changes in the branch to add a feature, which relies on the file existing
- you make bug fixes in master (cannot be discarded)
- you merge some day, and the file is gone!
How to Reproduce:
Create a git repo with one file.
git init echo "test" > test.txt git add . git commit -m "initial commit"
Create a branch
git branch branchA
Delete the file in master
git rm test.txt git commit -m "removed file from master"
Make ANY changes in branchA that don't touch the deleted file (it has to be unchanged to avoid Conflict)
git checkout branchA touch something.txt git add . git commit -m "some branch changes"
From here, any way I've found to merge these two branches, the test.txt file is deleted. Assuming we were relying on the file for branchA
, this is a big problem.
Failing examples:
Merge 1
git checkout branchA
git merge master
ls test.txt
Merge 2
git checkout master
git merge branchA
ls test.txt
Rebase 1
git checkout branchA
git rebase master
ls test.txt
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
这是一个有趣的问题。因为您在创建
BranchA
之后删除了该文件,然后将master
合并到BranchA
中,所以我不确定 Git 如何能够意识到存在冲突。错误合并后,您可以撤消,然后重新合并,但添加回文件:
This is an interesting issue. Because you deleted the file after
BranchA
was created, and then are mergingmaster
intoBranchA
, I'm not sure how Git would be able to realize there is a conflict.After the bad merge you can undo, and then re-merge, but add back the file:
Casey 的示例不适用于我的案例 - 我无法从
master
中签出test.txt
,因为它不再位于该分支:很高兴我可以从
branchA
自己的HEAD
中提取文件:Casey's example didn't work for my case - I couldn't checkout
test.txt
frommaster
, because it was no longer in that branch:Happily I could pull the file out of
branchA
's ownHEAD
:在这种情况下,为了快速修复,请“git revert”删除该文件的提交。
当将来出现这种情况时,更好的处理方法是确保新文件的创建发生在分支上。然后,当您合并时,它会添加到 master 上,但同时您没有该文件位于 master 中。
For a quick fix in this case, "git revert" the commit that deleted the file.
When this situation comes up in the future, the better way to handle it is to ensure that the creation of the new file happens on the branch. Then it gets added on master when you merge, but you don't have the file lying around in master in the meantime.
我的解决方案是简单地修改我需要保留的文件(添加无论如何都需要的注释)并在目标分支上提交这些更改,从而生成合并冲突,可以使用 git add 轻松解决/code> 和正常提交。
我的历史是这样的。为了保护无辜者,分支名称已更改。
git merge master
on feature_branch 导致原始文件被删除(当然),git reset --hard
到合并之前My solution to this was to simply modify the files I needed to keep (added a comment which was needed anyway) and commit those changes on the target branch, thus generating a merge conflict which could easily be resolved with a
git add
and a normal commit.My history went something like this. Branch names have been changed to protect the innocent.
git merge master
on feature_branch causes original files to be removed (of course),git reset --hard
to before the merge需要修改branch中的文件,以免与trunk中的delete发生合并冲突。
例如,如果您删除主干中头文件中某些内容的声明(因为没有任何东西需要它),并将对该声明的依赖项添加到分支中的某些非头文件中,则会发生完全相同的事情。当您合并时,由于分支不会触及标题(的那部分),因此它只会删除声明,并且事情将会中断。
每当您在多个地方拥有相互依赖且需要保持同步的内容时,合并就很容易默默地引入问题。这只是合并时必须了解和检查的事情之一。理想情况下,您使用编译时断言或其他构建时检查,这将使任何故障立即显现出来。
You need to modify the file in the branch, so that there's a merge conflict with the delete in the trunk.
The exact same thing will happen if you, for example, delete a declaration for something in a headerfile in the trunk (because nothing needs it), and add a dependency on that declaration to some non-header file(s) in the branch. When you merge, since the branch doesn't touch (that part of) the header, it will just delete the declaration and things will break.
Whenever you have stuff in multiple places that is interdependent and needs to be kept in sync, its very easy for a merge to silently introduce problems. Its just one of the things you have to know about and check when merging. Ideally, you use compile-time asserts or other build time checks that will make any failures immediately apparent.
git 也有同样的问题。当时正在分支机构开发一项功能,然后我的工作决定暂时搁置该功能以供稍后使用。因此,相关的功能文件已从 master 分支中删除,以允许应用程序部署时没有不必要的文件......暂时。现在我的工作需要我完成旧功能,当我尝试将旧分支合并或变基到当前主分支时,它会删除我需要的文件。
快速的解决方案是:修改需要保留在功能分支中的文件,添加并提交,然后与主分支合并。现在,这将导致合并冲突,而不是合并时的删除模式。现在您可以保留“我们的”对文件的更改。
问题是 git 将 HEAD 中的文件删除视为未更改,并将默认进入删除模式。具体来说:修改你需要的文件后,会输出
deleted in master and modded in HEAD
。重现解决方案:
git reset --hard origin/old_branch
git merge master
git add .
和git commit -m "fix业已删除的 HEAD"
git merge master
Same issue with git. Was working on a feature in a branch, then my job decided to sideline the feature for later. Thus the relevant feature files were deleted from master branch to allow app deployment without unnecessary files ... for the time being. Now my job needs me to finish the old feature and when I try to merge or rebase the old branch into the current master it deletes the files I need.
The quick solution is: Modify the files you need to keep in your feature branch, add and commit, and then merge with your master. This will now cause a merge conflict as opposed to deletion mode when merging. Now you can keep "our" changes to the files.
The problem is git sees the file deletion in HEAD as not being changed and will default into deletion mode. Specifically:
deleted in master and modified in HEAD
is outputted after you modify the files you need.Reproduce the solution:
git reset --hard origin/old_branch
git merge master
git add .
andgit commit -m "fix deleted HEAD"
git merge master
您可以在提交到当前合并分支之前签出文件,而不是反转合并(用户 Todd 的建议在 Alex Dean 解决方案上方的评论部分):
git checkout; -- path/to/file
例如,
git checkout 08ac9cf08f --classify.cpp
然后您可以推送您的分支。
Instead reversing merging, you could checkout file(s) from just before commit into your current merged branch (user Todd's suggestion at the comment section above Alex Dean's solution):
git checkout <commit hash or branch name> -- path/to/file
For example,
git checkout 08ac9cf08f -- classify.cpp
and then you could push your branch.
所以,我找到了另一个解决方案,我已经测试过它并且它有效:
--reverse
将为您提供旧提交的列表,到底部最新的)git show --name-only
列出您使用之前的命令获得的每个提交修改的所有文件git checkout; --
手动将每个文件添加到新分支这肯定类似于“逐个手动添加文件”,但如果您想确保较旧的提交不会优先于新分支掌握情况,就是这样。
顺便说一句,它肯定可以编写脚本。
So, I've found another solution, which I've tested and it works:
git log master..feature/<branch> --oneline --reverse
List all commits of the bad branch, since it was created from master (NOTE:--reverse
will give you a list from the older commit, to the newest at the bottom)git show --name-only <hash>
List all files modified by every commit you obtained with the command beforegit checkout <most_recent_commit_hash> -- <file_path>
Add manually each file to the new branchThis is for sure like "adding manually files one by one" but if you want to be sure that older commits don't prevail to the master situation, this is the way to go.
BTW, It could for sure be scripted.