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

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

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

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

我考虑过的方法:

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

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


当前回答

以下是如何让历史记录只跟踪来自另一个分支的几个文件,而不必大惊小怪,即使更“简单”的合并会带来更多您不希望的更改。

首先,您将采取不同寻常的步骤,提前声明您要提交的是合并,而Git根本不需要对工作目录中的文件执行任何操作:

git merge --no-ff --no-commit -s ours branchname1

…其中“branchname”是您声称要合并的任何内容。如果你马上提交,它不会做任何更改,但它仍然会显示来自其他分支的祖先。如果需要,也可以向命令行添加更多分支、标记等。不过,此时没有需要提交的更改,所以接下来从其他版本获取文件。

git checkout branchname1 -- file1 file2 etc.

如果要从多个其他分支合并,请根据需要重复。

git checkout branchname2 -- file3 file4 etc.

现在,来自另一个分支的文件位于索引中,准备提交,并具有历史记录。

git commit

在提交消息中,您需要做很多解释。

不过,请注意,如果不清楚的话,这是一件糟糕的事情。这不符合“树枝”的精神,而樱桃采摘是一种更诚实的方式来完成你将要做的事情。如果您想对上次未带来的同一分支上的其他文件进行另一次“合并”,它将以“已更新”消息阻止您。这是一种当我们应该分支时没有分支的症状,因为“from”分支应该是多个不同的分支。

其他回答

我想要的是:在一个新的分支中,以交互方式从一个分支(它有几个混乱的提交)中选择一个大块的提交。

如果diff中有任何二进制文件,gitdiff+gitapply将无法工作。

我的方法:

# New branch from a clean starting point, e.g. master
git checkout new-clean-branch origin/master

# Get all changes from the messy branch
# (quote the star so your shell doesn't expand it)
git checkout messy-branch -- '*'

# Unstage ("un-add") everything
git restore --staged .

# Interactively add hunks to be staged for commit
git add -p

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

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

1800 INFORMATION的答案完全正确。不过,作为Git的新手,“使用Git cherry pick”不足以让我在互联网上进行更多挖掘,所以我想我会发布一份更详细的指南,以防其他人也在类似的情况下。

我的用例是希望有选择地将别人的GitHub分支中的更改拉到我自己的分支中。如果您已经有一个具有更改的本地分支,则只需执行步骤2和5-7。

使用要引入的更改创建(如果未创建)本地分支。$git分支mybranch<基本分支>切换到它。$git结帐mybranch从其他人的帐户中删除所需的更改。如果还没有,则需要将它们添加为远程。$git远程添加repo-w-changes<git-url>把树枝上的东西都拔下来。$git pull-repos-w-changes-branch-i-want查看提交日志以查看所需的更改:$git日志切换回要将更改拉入的分支。$git原始付款分支Cherry用哈希一个接一个地选择你的提交。$git cherry-pick-x提交哈希

帽子提示:http://www.sourcemage.org/Git_Guide(存档副本)

我找到了一个解决这个问题的方法,这真的很简单。所以我只是把它放在这里给自己和其他想要使用这个解决方案的人。

答案假设我在包含单个文件file1.text的branch1中现在,我想将file1.txt与branch2中的另一个文件file2.txt合并。所以命令应该是,

git checkout --patch branch2 <path_of_file2.txt_in_context_of_branch2>

这会提示控制台,您需要输入特定字符以反映当前分支分支1中的更改。有时我用a来接受所有的帅哥。

我希望这个答案有帮助。谢谢