题 如何有选择地合并或从Git中的另一个分支选择更改?
我在一个新项目中使用git,该项目有两个并行 - 但目前是实验性的 - 开发分支:
master
:导入现有的代码库加上一些我一般都知道的mod
exp1
:实验分支#1
exp2
:实验分支#2
exp1
和 exp2
代表两种截然不同的建筑方法。直到我走得更远,我无法知道哪一个(如果有的话)会起作用。当我在一个分支中取得进展时,我有时会在另一个分支中进行编辑,并且只想合并那些。
将选择性更改从一个开发分支合并到另一个开发分支而将其他所有内容合并的最佳方法是什么?
我考虑过的方法:
git merge --no-commit
然后手动取消大量编辑,我不想在分支之间做出共同点。
手动将公共文件复制到临时目录中,然后执行 git checkout
移动到另一个分支,然后更多手动从temp目录复制到工作树中。
以上的变化。放弃了 exp
现在分支,并使用另外两个本地存储库进行实验。这使得手动复制文件更加简单。
所有这三种方法看起来都很乏味且容易出错。我希望有更好的方法;类似于过滤器路径参数的东西 git-merge
更有选择性。
1159
2018-01-16 04:55
起源
答案:
你用的是 摘樱桃 命令从一个分支获取单个提交。
如果您想要的更改不在单独提交中,请使用此处显示的方法 将提交拆分为单独的提交。粗略地说,你使用 git rebase -i
然后获得原始提交进行编辑 git reset HEAD^
那么,有选择地还原变化 git commit
将该位提交为历史记录中的新提交。
这里有另一种不错的方法 在红帽杂志,他们使用 git add --patch
或者可能 git add --interactive
如果要将不同的更改拆分为单个文件(在该页面中搜索“拆分”),则允许您仅添加部分块。
拆分更改后,您现在可以选择您想要的更改。
390
2018-01-16 06:01
我有与上面提到的完全相同的问题。但我发现了 这个 更清楚地解释答案。
概要:
签出要合并的分支的路径,
$ git checkout source_branch -- <paths>...
或有选择地合并帅哥
$ git checkout -p source_branch -- <paths>...
或者,使用重置,然后使用选项添加 -p
,
$ git reset <paths>...
$ git add -p <paths>...
最后提交
$ git commit -m "'Merge' these changes"
820
2017-09-03 08:48
要有选择地将文件从一个分支合并到另一个分支,请运行
git merge --no-ff --no-commit branchX
哪里 branchX
是要合并到当前分支的分支。
该 --no-commit
选项将暂存已由Git合并而不实际提交它们的文件。这将使您有机会根据需要修改合并的文件,然后自己提交。
根据您要合并文件的方式,有四种情况:
1)你想要一个真正的合并。
在这种情况下,您接受合并文件的方式是Git自动合并它们然后提交它们。
2)有些文件你不想合并。
例如,您希望保留当前分支中的版本并忽略要合并的分支中的版本。
要选择当前分支中的版本,请运行:
git checkout HEAD file1
这将检索版本 file1
在当前分支中覆盖 file1
由Git自动充电。
3)如果你想在branchX中使用该版本(而不是真正的合并)。
跑:
git checkout branchX file1
这将检索版本 file1
在 branchX
并覆盖 file1
由Git自动合并。
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
#
哪里 file1
, file2
,和 file3
是git成功自动合并的文件。
这意味着改变了 master
和 branchX
因为所有这三个文件已经组合在一起而没有任何冲突。
您可以通过运行来检查合并的完成方式 git diff --cached
;
git diff --cached file1
git diff --cached file2
git diff --cached file3
如果您发现某些合并不受欢迎,那么您可以
- 直接编辑文件
- 保存
git commit
如果你不想合并 file1
并希望保留当前分支中的版本
跑
git checkout HEAD file1
如果你不想合并 file2
并且只想要版本 branchX
跑
git checkout branchX file2
如果你想 file3
要自动合并,不要做任何事情。
Git已经在这一点上合并了它。
file4
上面是Git失败的合并。这意味着在同一行上发生的两个分支都发生了变化。您需要手动解决冲突。您可以通过直接编辑文件或对所需分支中的版本运行checkout命令来放弃合并完成 file4
成为。
最后,别忘了 git commit
。
241
2018-05-21 03:00
我不喜欢上述方法。使用cherry-pick非常适合选择单个更改,但如果您想要引入除了一些不良更改之外的所有更改,那将是一种痛苦。这是我的方法。
没有 --interactive
您可以传递给git merge的参数。
这是替代方案:
你在分支'功能'中有一些变化,你想要以一种不邋way的方式将一些但不是全部的变为'master'(即你不想挑选并提交每一个)
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并将功能更改为$ 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
85
2017-08-28 18:47
还有另外一种方法:
git checkout -p
它是一种混合 git checkout
和 git add -p
并且可能正是您正在寻找的:
-p, --patch
Interactively select hunks in the difference between the <tree-ish>
(or the index, if unspecified) and the working tree. The chosen
hunks are then applied in reverse to the working tree (and if a
<tree-ish> was specified, the index).
This means that you can use git checkout -p to selectively discard
edits from your current working tree. See the “Interactive Mode”
section of git-add(1) to learn how to operate the --patch mode.
73
2017-08-25 01:31
虽然其中一些答案非常好,但我觉得没有人真正回答OP的原始约束:从特定分支中选择特定文件。这个解决方案可以做到这一点,但如果有很多文件可能会很乏味。
让我们说你有 master
, exp1
,和 exp2
分支机构。您希望将每个实验分支中的一个文件合并为主文件。我会做这样的事情:
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
这将为您提供所需的每个文件的文件内差异。而已。没什么。在版本之间进行完全不同的文件更改很有用 - 在我的例子中,将应用程序从Rails 2更改为Rails 3。
编辑:这将合并文件,但进行智能合并。我无法弄清楚如何使用这种方法来获取文件内的差异信息(也许它仍然会出现极端的差异。除非你使用,否则像空白这样烦人的小东西会被合并回来 -s recursive -X ignore-all-space
选项)
48
2018-05-07 11:38
1800 INFORMATION的答案完全正确。然而,作为一个git noob,“使用git cherry-pick”还不足以让我在互联网上更多地挖掘这一点,所以我想我会发布一个更详细的指南以防其他人在类似的船。
我的用例是想有选择地将其他人的github分支中的更改转换为我自己的。如果您已经有一个包含更改的本地分支,则只需执行步骤2和5-7。
创建(如果未创建)包含您要引入的更改的本地分支。
$ git branch mybranch <base branch>
切换到它。
$ git checkout mybranch
从其他人的帐户中下拉您想要的更改。如果您还没有想要将它们添加为遥控器。
$ git remote add repos-w-changes <git url>
从他们的分支拉下一切。
$ git pull repos-w-changes branch-i-want
查看提交日志以查看所需的更改:
$ git log
切换回要将更改拉入的分支。
$ git checkout originalbranch
Cherry用哈希一个接一个地挑选你的提交。
$ git cherry-pick -x hash-of-commit
帽子提示: http://www.sourcemage.org/Git_Guide
42
2017-07-29 08:37
以下是您可以替换的方法 Myclass.java
档案 master
分支机构 Myclass.java
在 feature1
科。即使这样也会奏效 Myclass.java
不存在 master
。
git checkout master
git checkout feature1 Myclass.java
请注意,这将覆盖 - 而不是合并 - 而忽略主分支中的本地更改。
37
2018-02-27 22:42
实际上,简单的方法 合并 来自两个分支的特定文件,不仅仅用来自另一个分支的文件替换特定文件。
第一步:扩散分支
git diff branch_b > my_patch_file.patch
创建当前分支和branch_b之间差异的补丁文件
第二步:在匹配模式的文件上应用补丁
git apply -p1 --include=pattern/matching/the/path/to/file/or/folder my_patch_file.patch
关于选项的有用说明
您可以使用 *
作为包含模式中的通配符。
斜杠不需要转义。
此外,您可以使用--exclude将其应用于除匹配模式的文件之外的所有内容,或者使用-R反转补丁
-p1选项是* unix patch命令的保留,以及补丁文件的内容在每个文件名前加上 a/
要么 b/
(或者更多取决于补丁文件的生成方式),您需要将其剥离,以便它可以将实际文件计算到补丁需要应用到的文件的路径。
查看git-apply的手册页以获取更多选项。
第三步:没有第三步
显然你想要提交你的更改,但是谁说你在提交之前没有其他相关的调整。
22
2018-02-18 04:28
以下是如何让历史记录只关注来自另一个分支的几个文件,即使更“简单”的合并会带来更多您不想要的更改。
首先,您将采取不寻常的步骤,提前声明您要提交的内容是合并,而不是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”分支中应该是多个不同的分支。
20
2017-11-04 10:51
我知道我有点晚了,但这是我合并选择性文件的工作流程。
#make a new branch ( this will be temporary)
git checkout -b newbranch
# grab the changes
git merge --no-commit featurebranch
# unstage those changes
git reset HEAD
(you can now see the files from the merge are unstaged)
# now you can chose which files are to be merged.
git add -p
# remember to "git add" any new files you wish to keep
git commit
14
2017-10-29 20:54