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

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

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

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

我考虑过的方法:

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

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


当前回答

tl;博士

git checkout source_branch -- path/to/file
# resolve conflicts if any
git commit -am '...'

我遇到了和你上面提到的完全相同的问题。但我在解释答案时发现这一点更清楚。

摘要:

检查要合并的分支的路径,$git签出source_branch--<paths>。。。提示:它也可以像链接文章中看到的那样,不使用“--”。或者选择性地合并大块$git checkout-p source_branch--<paths>。。。

或者,使用reset,然后添加选项-p,

    $ git reset <paths>...
    $ git add -p <paths>...

最后提交$gitcommit-m“'合并'这些更改”

其他回答

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

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

实例

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

git checkout branchB .gitignore

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

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

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仍然没有这么方便的工具“开箱即用”。我在通过从当前版本分支中修复一些错误来更新一些旧版本分支(仍然有很多软件用户)时大量使用它。在这种情况下,通常需要从主干中的文件中快速获取一些代码行,而忽略许多其他更改(这些更改不应该进入旧版本)。。。当然,在这种情况下需要交互式三路合并,git checkout--patch<branch><file path>不能用于这种选择性合并。

您可以轻松完成:

只需将此行添加到global.gitconfig或local.git/config文件的[alias]部分:

[alias]
    mergetool-file = "!sh -c 'git show $1:$2 > $2.theirs; git show $(git merge-base $1 $(git rev-parse HEAD)):$2 > $2.base; /C/BCompare3/BCompare.exe $2.theirs $2 $2.base $2; rm -f $2.theirs; rm -f $2.base;' -"

这意味着您使用Beyond Compare。如果需要,只需更换您选择的软件即可。或者,如果不需要交互式选择性合并,可以将其更改为三向自动合并:

[alias]
    mergetool-file = "!sh -c 'git show $1:$2 > $2.theirs; git show $(git merge-base $1 $(git rev-parse HEAD)):$2 > $2.base; git merge-file $2 $2.base $2.theirs; rm -f $2.theirs; rm -f $2.base;' -"

然后这样使用:

git mergetool-file <source branch> <file path>

这将为您提供其他分支中任何文件的真正选择性树形合并机会。

我喜欢前面的“git交互式合并”答案,但有一个更简单。让Git使用交互式和到以下内容的重基组合为您实现这一点:

      A---C1---o---C2---o---o feature
     /
----o---o---o---o master

因此,您需要从“feature”分支(分支点“A”)中获取C1和C2,但目前没有其他分支。

# git branch temp feature
# git checkout master
# git rebase -i --onto HEAD A temp

正如前面的回答一样,这会让您进入交互式编辑器,在其中选择C1和C2的“pick”行(如上所述)。保存并退出,然后它将继续重新创建数据库,并为您提供分支“temp”和主机+C1+C2的HEAD:

      A---C1---o---C2---o---o feature
     /
----o---o---o---o-master--C1---C2 [HEAD, temp]

然后,您只需将master更新为HEAD并删除临时分支即可:

# git branch -f master HEAD
# git branch -d temp

下面是如何将master分支中的Myclass.java文件替换为feature1分支中的Myclass.java。即使master上不存在Myclass.java,它也可以工作。

git checkout master
git checkout feature1 Myclass.java

注意,这将覆盖-而不是合并-并忽略主分支中的本地更改。