使用git合并除文件移动和删除之外的分支

时间:2016-07-21 16:27:27

标签: git git-merge

与git合并时是否有办法不合并文件移动和删除?

我们制作了一个分支,然后通过删除或移动大量文件来修剪分支。在该分支中对重组文件进行了许多修改。我现在想要做的是将完整分支合并到修剪目录所做的更改,但仍然保留在已修剪分支中删除的所有文件,并将所有文件保留在其原始位置。

git是否有一种简单的方法可以合并来自修剪分支的更改,而不执行任何文件删除或移动?优选地,可以容易地处理已经移动了修改的文件的事实。

请注意,我主要关注更改的内容,而不是分支历史,因此使用挑选或重新定位的方法很好。 (只要我不必手动遍历提交历史记录就可以通过修改更改来隔离这些提交。)

我找到How do I ignore file deletions in a git branch for merging purposes?,但问题是前瞻性的,答案是“不要这样做”。在我的情况下,分支和删除已经发生。

2 个答案:

答案 0 :(得分:1)

这不是我在Git中会做的事情。可能有一种方法可以做到,但我会用一些shell脚本代替。您没有指定您的环境,但我的解决方案将适用于UNIX环境。无论如何都应该有运行bash脚本的工具。

首先,如果您的分支机构发生了分歧,以至于您希望在两个分支上进行更改,那么您可能需要进行变更。让我们致电您的分行masterdeletions。如果您已推送deletions以便其他人在该分支上工作,我可能会创建一个新的相同分支deletions2,我会在master上重新绑定以避免重写历史记录。你可能不想继续deletions工作,因为你必须重做它,但这样你就不会破坏任何东西。

然后我会通过克隆repo手动将所有文件从deletions2复制到master,并在repo的一个副本和另一个副本中的另一个分支中检出一个分支。然后我会列出所有跟踪的文件并使用一个简单的循环复制它们:

deletions2/ $ \
git ls-tree HEAD -r | while read f; do \
    # use -n to keep master versions, -f to keep deletions versions, \
    # or -i to choose manually for each file \
    cp -f "$f" ../master/ \
done

答案 1 :(得分:1)

以下是我处理它的方式。

与user2882096的答案一样,我将使用完整的删除前分支为master,修剪分支为deletions的约定。我还假设您正在使用存储库的根目录。

首先,git很容易被移动的文件搞糊涂,所以第一件事是在牺牲分支中反转移动。

git checkout -b deletions2 deletions
git merge-base deletions2 master # Note this SHA1 - substitute it in the following commands
git diff --diff-filter=R -M25% --raw SHA1 | awk '{system("mkdir -p `dirname " $(NF-1)"`; git mv " $NF " " $(NF-1) )}'
git commit

git diff命令使用diff-filter来仅删除在删除分支上发生的重命名(移动)。 -M25%意味着进行更广泛的重命名检测,查找除了被移动之外还具有高达75%修改的文件。 --raw将输出格式更改为更便于后期处理的格式。

awk命令只是一种扭转移动的方法。 (请注意,如果文件名中包含空格或时髦字符,则不一定非常强大。)这里唯一的复杂因素是git mv不会创建不存在的目录,因此mkdir -p basename位。

随着移动的撤消,我们可以获得修改和添加的补丁(但不是删除):

git diff --patch --diff-filter=AM -M25 SHA1 > modifications.patch

然后我们可以在合并点创建另一个牺牲分支,以允许我们应用更改。

git checkout -b temp SHA1
git apply modifications.patch # and resolve any issues
git merge master # To resolve conflicts with the current state of master

现在我们只需将临时分支合并回主服务器。

git checkout master
git merge temp

这将合并修改,但不会合并提交历史记录。如果您还希望合并提交历史记录:

git merge -s ours deletions2

-s ours告诉git merge合并提交历史记录,但保持文件当前状态。

最后注意事项:如果不使用git diffgit apply来制作补丁,那么使用git format-diffgit am可能会更好。但是,我无法使用--diff-filter选项使其正常工作。制作了适当的补丁,但它们并不适用。更熟悉这两者的人可能会有更好的成功。