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

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

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

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

我考虑过的方法:

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

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


当前回答

最简单的方法是将存储库设置为要合并的分支,然后运行

git checkout [branch with file] [path to file you would like to merge]

如果你跑步

git status

您将看到文件已暂存。。。

然后运行

git commit -m "Merge changes on '[branch]' to [file]"

易于理解的

其他回答

我发现这篇文章包含了最简单的答案。只需执行以下操作:

git checkout <branch from which you want files> <file paths>

实例

将.gitignore文件从branchB拉入当前分支:

git checkout branchB .gitignore

有关更多信息,请参阅文章。

我不喜欢上述方法。使用cherry pick可以很好地选择一个改变,但如果你想带来所有的改变,除了一些不好的改变,这是一种痛苦。这是我的方法。

没有可以传递给gitmerge的--interactive参数。

以下是备选方案:

您在分支“特性”中进行了一些更改,您希望以一种不拖泥带水的方式将其中的一些(但不是全部)提交给“主”(即,您不希望逐一挑选和提交)

git checkout feature
git checkout -b temp
git rebase -i master

# Above will drop you in an editor and pick the changes you want ala:
pick 7266df7 First change
pick 1b3f7df Another change
pick 5bbf56f Last change

# Rebase b44c147..5bbf56f onto b44c147
#
# Commands:
# pick = use commit
# edit = use commit, but stop for amending
# squash = use commit, but meld into previous commit
#
# If you remove a line here THAT COMMIT WILL BE LOST.
# However, if you remove everything, the rebase will be aborted.
#

git checkout master
git pull . temp
git branch -d temp

所以,只需将其包装在shell脚本中,将master更改为$to,并将feature更改为$from,就可以了:

#!/bin/bash
# git-interactive-merge
from=$1
to=$2
git checkout $from
git checkout -b ${from}_tmp
git rebase -i $to
# Above will drop you in an editor and pick the changes you want
git checkout $to
git pull . ${from}_tmp
git branch -d ${from}_tmp

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

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中合并子目录?

虽然其中一些答案很好,但我觉得没有人真正回答了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 commit1.commit2文件模式| git apply--索引和git提交

这样,您可以限制来自分支的文件模式的提交范围。

它是从Re窃取的:如何从一个分支到另一个分支仅提取几个文件?