协慌网

登录 贡献 社区

如何在 Git 中有选择地合并或选择来自另一个分支的更改?

我在一个新项目上使用 git,该项目有两个并行 - 但目前是实验性的 - 开发分支:

  • master :导入现有的代码库加上一些我一般都知道的 mod
  • exp1 :实验分支#1
  • exp2 :实验分支#2

exp1exp2代表两种截然不同的架构方法。直到我走得更远,我无法知道哪一个(如果有的话)会起作用。当我在一个分支中取得进展时,我有时会在另一个分支中进行编辑,并且只想合并那些。

将选择性更改从一个开发分支合并到另一个开发分支而将其他所有内容合并的最佳方法是什么?

我考虑过的方法:

  1. git merge --no-commit然后手动取消大量编辑,我不想在分支之间进行通用。

  2. 手动将公共文件复制到临时目录中,然后将git checkout移动到另一个分支,然后将更多手动从临时目录复制到工作树中。

  3. 以上的变化。暂时放弃exp分支并使用另外两个本地存储库进行实验。这使得手动复制文件更加简单。

所有这三种方法都显得乏味且容易出错。我希望有更好的方法; 类似于过滤器路径参数的东西会使git-merge更具选择性。

答案

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

摘要:

  • 签出要合并的分支的路径,

    $ git checkout source_branch -- <paths>...

    提示:它也可以不用--就像在链接帖子中看到的那样。

  • 或有选择地合并帅哥

    $ git checkout -p source_branch -- <paths>...

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

    $ git reset <paths>...
    $ git add -p <paths>...
  • 最后提交

    $ git commit -m "'Merge' these changes"

您可以使用cherry-pick命令从一个分支获取单个提交。

如果您想要的更改不在单独的提交中,那么使用此处显示的方法将提交拆分为单独的提交 。粗略地说,您使用git rebase -i来获取原始提交进行编辑,然后git reset HEAD^以选择性地还原更改,然后git commit commit 将该位提交为历史记录中的新提交。

在 Red Hat Magazine 中还有另一种不错的方法 ,他们使用git add --patch或者git add --interactive ,它允许你只添加一部分大块,如果你想将不同的更改分成单个文件(搜索在该页面中 “拆分”)。

拆分更改后,您现在可以选择您想要的更改。

要有选择地将文件从一个分支合并到另一个分支,请运行

git merge --no-ff --no-commit branchX

其中branchX是您要合并到当前分支的分支。

--no-commit选项将--no-commit已由 Git 合并的文件,而不实际提交它们。这将使您有机会根据需要修改合并的文件,然后自己提交。

根据您要合并文件的方式,有四种情况:

1)你想要一个真正的合并。

在这种情况下,您接受合并文件的方式是 Git 自动合并它们然后提交它们。

2)有些文件你不想合并。

例如,您希望保留当前分支中的版本并忽略要合并的分支中的版本。

要选择当前分支中的版本,请运行:

git checkout HEAD file1

这将检索当前分支中的file1版本,并通过 Git 覆盖file1 automerged。

3)如果你想在 branchX 中使用该版本(而不是真正的合并)。

跑:

git checkout branchX file1

这将检索branchXfile1版本并覆盖由 Git 自动合并的file1

4)最后一种情况是如果你只想在file1选择特定的合并。

在这种情况下,您可以直接编辑修改后的file1 ,将其更新为您想要的file1版本,然后提交。

如果 Git 无法自动合并文件,它会将文件报告为 “未合并 ” 并生成一个副本,您需要手动解决冲突。



为了进一步解释一个例子,假设你想将branchX合并到当前分支中:

git merge --no-ff --no-commit branchX

然后运行git status命令以查看已修改文件的状态。

例如:

git status

# On branch master
# Changes to be committed:
#
#       modified:   file1
#       modified:   file2
#       modified:   file3
# Unmerged paths:
#   (use "git add/rm <file>..." as appropriate to mark resolution)
#
#       both modified:      file4
#

其中file1file2file3是 git 已成功自动合并的文件。

这意味着所有这三个文件的masterbranchX中的更改已组合在一起而没有任何冲突。

您可以通过运行git diff --cached来检查合并是如何完成的;

git diff --cached file1
git diff --cached file2
git diff --cached file3

如果您发现某些合并不受欢迎,那么您可以

  1. 直接编辑文件
  2. 保存
  3. git commit

如果您不想合并file1并希望保留当前分支中的版本

git checkout HEAD file1

如果您不想合并file2并且只想在branchX该版本

git checkout branchX file2

如果您希望自动合并file3 ,请不要执行任何操作。

Git 已经在这一点上合并了它。


上面的file4是 Git 失败的合并。这意味着在同一行上发生的两个分支都发生了变化。您需要手动解决冲突。您可以通过直接编辑文件或对希望file4成为分支的版本运行 checkout 命令来放弃合并完成。


最后,不要忘记git commit