2017-07-14 351 views
0

我为子项目创建了master的my_branch(请参见下图)。我不得不从my_branch中删除很多文件,因为它们与子项目无关,但这些文件仍然在master中需要。有一段时间,开发发生在master和my_branch中。重建或合并Git分支但保留已删除的文件

既然子项目已经完成,我想要将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 
+0

这里思考了我的头顶部开始my_branch,然后提交主。将my_branch合并(或重新绑定)为master。然后再次追踪所有文件? – jrahhali

回答

1

UPDATE - 我以前的如何处理一个重订期间edit提交的解释是不够不清楚是不准确的。澄清


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

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

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

最好的程序取决于很多事情。有些更普遍可行(但更多参与),而另一些更容易执行(但只有在某些事情是真的时才起作用)。

听起来好像这些文件不是一次全部删除,而是在发生其他更改的相同提交中被删除。

这可能是一个交互式重新分配工作。当然你可以用filter-branch做到这一点。这两者的一些组合也可能是一种选择。

如果my_branch与您所描绘的线性一样 - 在分支上没有合并提交 - 那么您可能可以通过交互式底图获取。

git rebase --interactive master my_branch 

在弹出待办列表,标注任何承诺可能包含不必要的缺失为edit(而不是默认的pick)。随着rebase的进展,它会在暂时提交每个补丁后暂停。要找到不需要的删除,你可以做类似

git diff --diff-filter D --no-renames --name-only HEAD^ 

(更简单的命令将工作;这试图让刚刚被删除的文件名的列表,以便您可以检查要反转哪些特别的,你可能会或可能。不想要--no-renames;它的目的是为了避免意外触发重命名检测,可能会阻止删除显示,但如果你真的重命名了很多文件,这将导致它显示为删除。)

要反转特别删除

git checkout HEAD^ -- path/and/filename 

当你有删除逆转

git add . 
git commit --amend 

以上底垫命令也将完成你的工作的重订基期到的master尖端。如果你不需要想要 - 例如如果你想工作合并到master而是 - 你可以不喜欢

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

的东西,如果这似乎说明书,或者如果有,将阻止其工作的复杂性,那么你可能会喜欢filter-branch - 但要警告说,如果历史很大,这可能会很缓慢。

在这种情况下,你需要的是一个tree-filter重新添加删除的文件。您在删除在主untrack所有文件 - 我会通过获取所有文件的本地副本作为合并基础的

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 
+0

谢谢,马克,这是教育。我能够使用你的方法来进行合并(我并不需要所有这些)。我也使用了部分Ben的答案。 –

1

master分支,做了合并,并通过--no-commit标志:

git merge my_branch --no-commit

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

git reset HEAD <file>

git checkout -- <file>

命令git status会告诉你哪些文件是要删除,如果你愿意的话,你可以分析一个脚本这个输出选择性地复位/签出的所有被删除的文件

,然后进行提交最终的结果:

git commit

+0

听起来不错 - 我会尽量报告。 –

+1

虽然这看起来很简单,应该工作,但我不一定会推荐它。原因是如果他们遇到你的合并,进一步的重组可能会造成严重破坏。如果使用默认策略合并会成功(但会产生不想要的结果),那么使用'--no-commit'来编辑合并会有些危险。如果你知道你永远不能通过合并这个回购合并,如果你已经有所谓的“邪恶合并” - 那就没问题。如果没有,我会考虑采取不同的方法(我将作为一个单独的答案发布) –

+0

感谢Ben和Mark:我使用了您的建议的元素,但是Mark's更有用。 –