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

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

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

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

我考虑过的方法:

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

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


当前回答

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

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

git checkout --patch branch2 <path_of_file2.txt_in_context_of_branch2>

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

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

其他回答

我不喜欢上述方法。使用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

我将专注于我感兴趣的这个问题的子集:我有两个分支,我想将一个文件伪合并到另一个文件中。

(我说“伪合并”是因为我不需要或不希望合并提交;我只想以我认为合适的方式合并文件两个版本的贡献。)

我的方法基于https://stackoverflow.com/a/39916536/341994.不幸的是,这个问题是重复的(在我看来,这是错误的:它不是这个问题的重复,回答和重复是错误的,这是回答者在那里做的)。但这个答案有一些问题,所以我已经现代化并清理了方法。我使用恢复而不是签出和重置,并且我不必提交任何不需要的东西。

好吧,假设我有三个文件:

$ ls
a   b   f

但我只想伪合并其中一个,a,来自另一个分支。让我们看看他们,看看情况会是什么样子。这是我的版本:

$ cat a
line one
line two
line three
line four
line five

以下是其他分支机构的版本:

$ git show otherbranch:a
line one
line two edited
line three
line four
line five
line six

现在这里的技巧是,我们将使用索引作为草稿(毕竟,这是它的用途)。因此,我们首先(步骤1)确保将我们的版本复制到索引中:

$ git add a

现在(步骤2)我们可以使用restore从其他分支获取版本(现在,restore比checkout更好,因为它可以让我们更清楚地说话):

$ git restore --source otherbranch a

乍一看,这看起来很糟糕。我们现在已经用其他分支的版本完全覆盖了我们的a,如您所见:

$ cat a
line one
line two edited
line three
line four
line five
line six

但别担心!如您所见,以前版本的仍在索引中:

$ git diff a
diff --git a/a b/a
index abf51fa..333614b 100644
--- a/a
+++ b/a
@@ -1,6 +1,7 @@
 line one
-line two
+line two edited
 line three
 line four
 line five
+line six

很好,现在我们准备好了关键步骤(步骤3)。我们将文件从工作树添加到索引中进行交互式补丁。

我们可以说git add-p a来启动交互式补丁程序,在这种情况下,我们一次只能得到一个大块。但在这种情况下,只有一个帅哥,我无论如何都想编辑它,所以我说:

$ git add --e a

结果是我们在编辑器中打开了一个diff补丁文件!它看起来像这样:

 line one
-line two
+line two edited
 line three
 line four
 line five
+line six

通过仔细编辑,我们现在可以决定我们要接受哪些部分,不接受哪些部分。让我们接受“第六行”,而不是“第二行已编辑”。所以我们编辑如下:

 line one
 line two
 line three
 line four
 line five
+line six

我们关闭编辑器,补丁应用于a的索引版本。但我们还没有完全完成!a的另一个分支版本仍然位于工作树中:

$ cat a
line one
line two edited
line three
line four
line five
line six

我们喜欢的版本在索引中,记得吗?为了实现这一点,(步骤4)我们只需简单地调用gitrestore(同样,这是现代的方式;restore比reset更好,可以应用于单个文件):

$ git restore a

现在我们的a是正确的,我们都完成了:

$ cat a
line one
line two
line three
line four
line five
line six

我们现在可以承诺,但我们不必;我们已经完成了既定目标。

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

第一步:区分分支

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 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

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(存档副本)