Git部分合并,而不是整个分支

76

我阅读了有关在Git 中合并公共和私有分支同时保持两个分支中特定文件完好无损的技巧等方面的一些技巧,但没有找到解决方案。

在我的情况下,我需要进行相反的合并策略。在并行开发中,我必须在任意分支之间保持某些文件相同。另一方面,我不想进行压缩或无提交合并,因为差异很大,可能会破坏测试分支的当前状态。

我想要的是像这样的东西

git checkout testing

git merge config.xml -b development 或者 git merge config\*.xml -b development

我猜这就像git merge-files ...命令,但第二个文件是来自分支而不是来自文件系统。这可行吗?还是说可能有一种解决方法?子模块?属性?

谢谢


2
Cherry picks 会创建一个重复的提交,而这可能会导致过多的合并冲突,或者更糟糕的是,没有冲突,却选错了代码。@Vadzim 的评论链接到正确的答案,如果你想进行真正的部分合并,那么当 cherry picked 的重影相遇时,它将允许你的分支适当地调和。这个链接指向一个由10部分组成的博客文章,你可能需要读两遍才能理解,但如果你真的想了解 git 合并,那么这个时间是值得的。 - Brain2000
4个回答

69

有几件事情可以做。

首先,您可以挑选您想要的更改,这仅适用于单个提交。例如,如果有一个仅涉及config.xml的更改,您可以使用cherry-pick命令来挑选它。

$ git cherry-pick $COMMIT_ID_YOU_WANT

你也可以直接从开发分支中获取config.xml文件:

$ git checkout testing
$ git checkout development -- config.xml

这将使你得到与开发分支中相同版本的config.xml文件,但请注意,它不会拉取文件更改的历史记录。


这就是我正在寻找的。谢谢。只有一个愿望,如果我能写 git cherry-pick $COMMIT_ID config.xml 就太奢侈了。好的,这是对git论坛的一个愿望。 - olegtaranenko
11
对于第二种解决方案:如果测试分支合并到开发分支中,这会导致合并冲突吗?我有这样一种情况,我想把一个功能分支的更改带到另一个分支中,但我不确定是否明智,因为当这两个分支合并回主分支时,可能会引起大量冲突。 - progician
执行以下命令是否必要? git checkout development -- config.xml - RobinReborn
@RobinReborn:不,只有当您还有一个与文件同名的分支时才需要,但我总是出于习惯添加它。 - mipadi

24
如果您只想应用对一定范围的提交所做的更改(这也可以是单个提交),并且仅应用于文件的子集,则执行以下操作:
git diff commit1..commit2 filepattern | git apply --index && git commit

你也可以只应用上述模式,不包括git commit,检查你的暂存区以确保所有更改都是所需的,最后手动提交暂存区。

链接无法使用 - AH.
没问题,我已经删除了参考链接。 - lumpidu

13

这是一个存储库,包含逐步说明部分合并的危险性并展示正确方式的文档。

https://gitlab.com/bimlas/learning-by-testing-git-partial-merge/tree/doc

简而言之:

合并必须是它所应该是的:分支的联合。如果您进行合并提交但未合并所有文件,并且稍后尝试合并相同的分支,则 Git 认为您在第一次合并提交中合并了所有内容,因此早期提交不重要,它会跳过第一次合并之前未合并的更改。

使用 checkout 将文件从一个分支复制到另一个分支:

git checkout BRANCH -- FILE
git commit -m "Partial merge"

刚刚修复了链接。 - bimlas
-- 是什么意思? - khatchad
2
@RaffiKhatchadourian 它用于将Git命令和参数与文件列表分开。请参见https://dev59.com/YWYr5IYBdhLWcg3w499-#13321491 - bimlas
只是想了解一下这里的作者问题以及其他帖子。以后是否能够确定对文件所做的更改的原始作者?如果不能,至少在提交信息中使用类似于“从提交$COMMIT_HASH和分支$BRANCH_NAME部分合并$FILENAME”这样的信息可能更加政治正确。 :) - undefined

6
可以直接从git-tree中选择文件进行合并。
我建议的做法是这样的:
$ git ls-tree development -- config.xml
$ git show <blob-hash> > config.xml.development

然后获取共同基础:
$ git ls-tree $(git merge-base HEAD development) -- config.xml
$ git show <blob-hash> > config.xml.base

最后:
$ git merge-file config.xml config.xml.base config.xml.development 不过我没有测试过。
在像zsh这样的shell中,您可以使用以下方法避免将blob保存到临时文件中:
$ git merge-file config.xml =(git show <base-blob-hash>) =(git show <dev-blob-hash>)

1
在Bash中,您可以执行以下操作:$ git merge-file config.xml $(git show <base-blob-hash>) $(git show <dev-blob-hash>) - Spark

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接