Rebase或Merge Git分支但保留已删除的文件

时间:2017-07-14 18:19:19

标签: git github

我从master中创建了my_branch(参见下图)以获取子项目。我不得不从my_branch中删除很多文件,因为它们与子项目无关,但在master中仍然需要这些文件。有一段时间,开发工作正在master和my_branch中进行。

现在子项目已经完成,我想将my_branch中的更改重新绑定或合并到master。但我想保留my_branch中删除但仍存在于master中的所有文件。最简单的方法是什么?

我意识到我应该创建一个单独的存储库并重构项目。但考虑到手头的情况,我该怎么做,最好不要手动?

不幸的是,我无法假设所有已删除的文件都在单独的提交中。

* 172c3f3 (origin/my_branch, my_branch) comment
| *   e4f6849 (origin/master, origin/HEAD, master) Merge branch asdf
| |\  
| | * c796e73 aafg
| |/  
| *   75720e5 Merge branch zxcv
| |\  
| | * 7c694e9 changes
| |/  
* | 61370ac some
* | 8afc0be development,
* | d14263b bugfixes,
* | 0d5a17f testing,
* | 588cf8f maybe some cleanup
* | 588cf8f here and there
* | e1f990b and a lot of files
* | 146212b removed
* | 09c6278 but they are still needed in master
|/  
*   9a53a83 my_branch created here

2 个答案:

答案 0 :(得分:1)

来自master分支,进行合并并传递--no-commit标记:

git merge my_branch --no-commit

现在您可以取消删除合并要删除的文件:

git reset HEAD <file>

git checkout -- <file>

命令git status将显示要删除的文件,如果您愿意,可以使用脚本解析此输出以选择性地重置/检出所有已删除的文件

然后继续提交最终结果:

git commit

答案 1 :(得分:1)

更新 - 我以前关于如何在rebase期间处理edit提交的解释不清楚是不准确的。澄清

一种可行的方法(如Ben所建议的)是编辑合并。存在潜在的缺点,因为这种合并将违反某些命令所做的假设(例如rebase,即使给出--preserve-merges也是如此。这可能导致此类命令在报告成功时静默生成损坏的结果。

有另一种选择,虽然它更复杂。它还涉及重写分支的历史,但你提到你可能会重新分支分支,所以我认为这不是问题。

这里的想法是丢弃历史记录中的文件删除,以便文件始终存在,处于创建分支时的状态。 (说实话,这应该是首先应该做的事情。)

最好的程序取决于很多事情。有些更普遍可行(但更多参与),而其他更容易执行(但只有在某些事情成立时才有效)。

听起来这些文件并非全部被删除,并且在发生其他更改的相同提交中被删除。

交互式rebase可能会起作用。当然你可以用filter-branch来做。两者的某种组合也可能是一种选择。

如果my_branch与您描述的一样线性 - 在分支上没有合并提交 - 那么您可能会使用交互式rebase。

git rebase --interactive master my_branch

在弹出的TODO列表中,标记任何可能包含edit不需要的删除的提交(而不是默认的pick)。随着rebase的进展,它会在暂时提交每个补丁之后暂停。要查找不需要的删除,您可以执行类似

的操作
git diff --diff-filter D --no-renames --name-only HEAD^

(更简单的命令将起作用;这会尝试仅获取已删除文件名的列表,以便您可以检查要反转的文件名。特别是,您可能想要也可能不想要--no-renames;它可以意味着避免意外触发重命名检测,这可能会阻止删除显示,但如果你真的重命名了很多文件,这将导致htem显示为删除。)

撤消特定删除

git checkout HEAD^ -- path/and/filename

当你删除了删除

git add .
git commit --amend

上述rebase命令还将完成您的工作重新定位到master的提示。如果您想要那样 - 例如如果你想将工作合并到master - 你可以做类似的事情

git rebase --interactive `git merge-base my_branch master` my_branch

如果这似乎是手动的,或者如果有复杂性使其无法工作,那么您可能更喜欢filter-branch - 但要注意,如果历史很大,这可能会很慢。

在这种情况下,您需要的是tree-filter重新添加已删除的文件。我将从合并基础

获取所有文件的本地副本开始
git checkout `git merge-base master my_branch`
cp all/the/files/that/were/deleted some/path/where/I/can/find/them/later

然后

git filter-branch --tree-filter 'cp some/path/where/I/can/find/them/later all/the/files/that/were/deleted' -- my_branch