我正在一个新项目中使用Git,该项目有两个并行但目前处于试验阶段的开发分支:

master:导入现有的代码库,再加上一些我通常确信的修改exp1:实验分支#1exp2:实验分支#2

exp1和exp2表示两种非常不同的体系结构方法。在我进一步相处之前,我无法知道哪一个(如果有的话)会起作用。当我在一个分支中取得进展时,我有时会对另一个分支进行有用的编辑,并希望仅合并这些编辑。

将一个开发分支中的选择性更改合并到另一个分支中,同时保留其他所有内容的最佳方法是什么?

我考虑过的方法:

gitmerge——无需提交,然后手动取消大量编辑,我不想在分支之间共享这些编辑。手动将通用文件复制到临时目录中,然后git checkout移动到另一个分支,然后更多地手动将临时目录复制到工作树中。在上述基础上的变化。暂时放弃exp分支,使用另外两个本地存储库进行实验。这使得手动复制文件更加简单。

所有这三种方法都显得乏味且容易出错。我希望有更好的方法;类似于过滤器路径参数,可以使gitmerge更有选择性。


当前回答

一种按文件选择性合并/提交的简单方法:

git checkout dstBranch
git merge srcBranch

// Make changes, including resolving conflicts to single files
git add singleFile1 singleFile2
git commit -m "message specific to a few files"
git reset --hard # Blow away uncommitted changes

其他回答

如果您只需要合并一个特定的目录并保留所有其他内容,同时保留历史记录,那么您可以尝试这样做。。。在实验之前,从主对象创建一个新的目标分支。

下面的步骤假设您有两个分支目标分支和源分支,并且要合并的目录目录位于源分支中。另外,假设您有其他目录(如dir)保留在目标中,您不想更改并保留历史记录。此外,假设要合并的目录中存在合并冲突。

git checkout target-branch
git merge --no-ff --no-commit -X theirs source-branch
# the option "-X theirs", will pick theirs when there is a conflict. 
# the options "--no--ff --no-commit" prevent a commit after a merge, and give you an opportunity to fix other directories you want to retain, before you commit this merge.

# the above, would have messed up the other directories that you want to retain.
# so you need to reset them for every directory that you want to retain.
git reset HEAD dir-to-retain
# verify everything and commit.

如果您没有太多的文件被更改,这将使您没有额外的提交。

1.临时复制分支$git结帐-b temp_branch

2.重置为上次所需提交$git reset--hard HEAD~n,其中n是需要返回的提交次数

3.从原始分支签出每个文件$git签出原点/original_branch文件名.ext

现在,如果需要,您可以提交并强制推送(覆盖远程)。

虽然其中一些答案很好,但我觉得没有人真正回答了OP的原始约束:从特定分支中选择特定文件。这个解决方案可以做到这一点,但如果有很多文件,可能会很乏味。

假设您有master、exp1和exp2分支。您希望将每个实验分支中的一个文件合并到master中。我会这样做:

git checkout master
git checkout exp1 path/to/file_a
git checkout exp2 path/to/file_b

# Save these files as a stash
git stash

# Merge stash with master
git merge stash

这将为您提供所需的每个文件的文件差异。没什么了。一点也不差。在不同版本之间进行完全不同的文件更改非常有用——在我的例子中,将应用程序从RubyonRails 2更改为RubyonRails 3。

这将合并文件,但它会进行智能合并。我无法弄清楚如何使用此方法获取文件差异信息(也许对于极端的差异,它仍然会这样做。除非使用-s递归-X忽略所有空格选项,否则像空格这样的恼人的小东西会被合并回来)

简单的方法是,实际上合并来自两个分支的特定文件,而不仅仅是用另一个分支的文件替换特定文件。

第一步:区分分支

git diff branch_b>my_patch_file.patch

创建当前分支和branch_b之间差异的修补程序文件

第二步:对匹配模式的文件应用补丁

git apply-p1--include=pattern/匹配/the/path/to/file/或/folder my_patch_file.patch

关于选项的有用说明

您可以在include模式中使用*作为通配符。

斜杠不需要逃避。

此外,您可以改用--exclude并将其应用于除与模式匹配的文件之外的所有文件,或使用-R反转补丁

-p1选项是*Unix修补程序命令的一个保留,并且事实上,修补程序文件的内容在每个文件名前面加上/或b/(或更多,取决于修补程序文件是如何生成的),您需要删除这些文件,这样它就可以找出真正的文件到需要应用修补程序的文件的路径。

查看git应用程序的手册页以了解更多选项。

第三步:没有第三步

很明显,你想提交你的更改,但谁能说你在提交之前没有其他相关的调整。

您可以使用读取树将给定的远程树读取或合并到当前索引中,例如:

git remote add foo git@example.com/foo.git
git fetch foo
git read-tree --prefix=my-folder/ -u foo/master:trunk/their-folder

要执行合并,请改用-m。

另请参阅:如何在Git中合并子目录?