如何选择合并或选择改变从另一个分支?
-
19-08-2019 - |
题
我令在一个新的项目,有两个平行的--但是目前的实验--发展分支:
master
:进口的现有codebase加一些功能,我一般的肯定exp1
:实验支#1exp2
:实验支#2
exp1
和 exp2
代表两个非常不同的建筑的方法。直到我得到进一步沿着我没有办法知道哪个(如果任何一)将工作。为我取得进展的一个分支有时候我会有的编辑,将是有用的,在其他分支,并谨合并仅仅是这些。
什么是最佳的方式合并的选择性变化,从一个发展到另一个分支,同时留下的一切?
办法我认为:
git merge --no-commit
随后撤回手册的大量编辑,我不想让之间共同分支机构。手册的复制的共同文件纳入一个临时目录后
git checkout
移动到其它分支机构,然后更多的手册复印出的临时目录入工作树。一变化,上面。放弃的
exp
分支机构现在和使用的两个额外的当地储存库的试验。这使该手册的复制的文件更加简单。
所有这三种办法似乎繁琐且容易出错。我希望有一个更好的办法;一个类似于一个过滤器的路径参数,这将使 git-merge
更具选择性。
解决方案
您可以使用 cherry-pick 命令从中获取单个提交一个分支。
如果所需的更改不在单独的提交中,请使用此处显示的方法提交到单个提交中。粗略地说,您可以使用git rebase -i
来编辑原始提交,然后使用git reset HEAD^
选择性地还原更改,然后使用git commit
将该位作为历史记录中的新提交提交。
“红帽”杂志中还有一个不错的方法,他们使用git add --patch
或可能的git add --interactive
,如果您想将不同的更改拆分给一个人,则可以只添加大块的一部分文件(在该页面中搜索“拆分”)。
对更改进行拆分后,您现在就可以选择所需的内容了。
其他提示
我遇到了与您上面提到的完全相同的问题。但是我发现这更清楚地解释了答案。
摘要:
-
从您要合并的分支中检出路径, 通用标签
提示:它也可以不使用链接帖子中所见的
--
。 -
或有选择地合并大块 通用标签
或者,使用reset,然后添加
-p
选项,$ git checkout source_branch -- <paths>...
-
最终提交
$ git checkout -p source_branch -- <paths>...
以选择性地合并文件从一个分支进入另一个分支,运行
git merge --no-ff --no-commit branchX
哪里 branchX
是的支你想要合并到目前的分支。
的 --no-commit
选项将阶段的文件,已经合并通过Git没有实际犯他们。这会给你机会来修改本合并的文件但是你想要的然后提交他们自己。
取决于你怎么想的合并文件中,有四种情况:
1)你想要一个真正的合并。
在这种情况下,接受合并文件的方式Git合他们自动的,然后提交。
2)有一些文件你不想要合并。
例如,你想保留的版本,在当前的分支,而忽略该版本在分合并。
选择在目前的分支中,运行:
git checkout HEAD file1
这将检索的版本 file1
在目前的分支和复盖 file1
automerged通过饭桶。
3)如果你想的版本在branchX(而不是一个真正的合并).
运行:
git checkout branchX file1
这将检索的版本 file1
在 branchX
和复盖 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
#
哪里 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
要合并自动的,不要做任何事情。
混帐具有已经合并,它在这一点上。
file4
上面是一个失败的合并通过饭桶。这意味着有改变在这两种分支,发生在同一条线上。这是在那里你会需要解决冲突。你可以放弃合并后通过编辑的文件直接或运行结帐指令为该版本在支你想要的 file4
成。
最后,不要忘记 git commit
.
我不喜欢上述方法。使用cherry-pick非常适合选择单个更改,但是如果您想带入所有更改(除了一些不好的更改),这将是一个痛苦。这是我的方法。
没有--interactive
参数可以传递给git merge。
这里是替代方法:
您在分支“功能”中进行了一些更改,并且希望以一种不草率的方式将其中一些但不是全部带入“主”(即,您不想挑剔并提交每个)> 通用标签
因此,只需将其包装在shell脚本中,将master更改为$ to,然后将功能更改为$ from,就可以了: 通用标签
还有另一种解决方法: 通用标签
这是git checkout
和git add -p
之间的混合,可能正好是您要寻找的东西
通用标签
虽然这些答案中的一些很好,但我觉得没有一个人能真正回答OP的原始约束:从特定分支中选择特定文件。此解决方案可以做到这一点,但是如果文件很多,可能会很乏味。
假设您有master
,exp1
和exp2
分支。您想将每个实验分支中的一个文件合并到master文件中。我会做这样的事情:
通用标签
这将为您提供每个文件所需的文件内差异。而已。没什么。在版本之间进行完全不同的文件更改很有用-就我而言,将应用程序从Rails 2更改为Rails 3。
编辑:这将合并文件,但会进行智能合并。我无法弄清楚如何使用这种方法来获取文件中的差异信息(也许仍然会存在巨大差异。除非您使用-s recursive -X ignore-all-space
选项,否则讨厌的小东西如空格将被重新合并)
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
在这里,您可以用Myclass.java
分支中的master
替换Myclass.java
分支中的feature1
文件。即使Myclass.java
上不存在master
,它也将起作用。
通用标签
请注意,这将覆盖-不会合并-而是忽略master分支中的本地更改。
一种简单的方法,实际上是合并来自两个分支的特定文件,而不仅仅是用来自另一个分支的特定文件替换特定的文件。
第一步:将树枝分开
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
git diff branch_b > my_patch_file.patch
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的更多选项。
第三步:没有第三步
很显然,您想提交更改,但是谁又说您在提交之前没有其他相关的调整。
在这里,即使更“简单”的合并会带来很多您不想要的更改,您也可以通过这种方式来获得历史记录,从而仅以最小的麻烦跟踪另一个分支中的几个文件。
首先,您将采取不寻常的步骤,即预先声明要提交的内容是合并,而git根本不对工作目录中的文件做任何事情: 通用标签
。 。 。其中“分支名称”是您声称要合并的内容。如果您要立即提交,则不会进行任何更改,但仍会显示来自另一个分支的祖先。您可以添加更多分支/标签/等。如果需要,也可以使用命令行。不过,此时还没有要提交的更改,因此,接下来要从其他修订版中获取文件。 通用标签
如果要从多个分支合并,请根据需要重复。 通用标签
现在,来自另一个分支的文件都在索引中,可以随时提交,并带有历史记录。 通用标签
,您将在该提交消息中进行很多说明。
但是请注意,以防万一,这是很麻烦的事情。这与“分支”的目的无关,在这里,“摘樱桃”是一种更诚实的方式来做您想做的事情。如果您想对上次未带过的同一分支上的其他文件进行另一次“合并”,则会显示“已经更新”消息,从而阻止您。这是我们不应该分支的症状,在“ from”分支中应该有多个不同的分支。
我知道我来晚了,但这是我合并选择性文件的工作流程。 通用标签
最简单的方法是将存储库设置为要合并的分支,然后运行, 通用标签
如果您运行 通用标签
您将看到文件已经上演...
然后运行 通用标签
简单。
奇怪的是,git仍然没有“开箱即用”的便捷工具。通过仅从当前版本分支中获取一些错误修正来更新一些旧版本分支(仍然有很多软件用户)时,我会大量使用它。在这种情况下,通常需要快速从树干中的文件中快速获取一些行代码,而忽略了许多其他更改(这些更改本不应该包含在旧版本中)...当然,在这种情况下,需要交互式三向合并,但git checkout --patch <branch> <file path>
不能用于此选择性合并。
您可以轻松做到:
只需将此行添加到全局[alias]
或本地.gitconfig
文件中的.git/config
部分:
通用标签
这意味着您使用“超越比较”。如果需要,只需更改为您选择的软件即可。或者,如果不需要交互式选择性合并,则可以将其更改为三向自动合并: 通用标签
然后这样使用: 通用标签
这将为您提供其他分支中任何文件的真正选择性 tree-way 合并机会。
这并不是您要找的东西,但这对我很有用: 通用标签
它是一些答案的组合。
我遇到了与您上面提到的完全相同的问题。但我发现这个git博客更清晰地解释了答案。
上面链接中的命令: 通用标签
我会做
git diff commit1..commit2文件模式|git-apply --index && git commit
这样,您可以限制分支中文件模式的提交范围。
从以下地址窃取: http://www.gelato.unsw.edu.au / archives / git / 0701 / 37964.html
我喜欢上面的“ git-interactive-merge”答案,但是有一个更简单。让git使用交互式和以下的rebase组合为您完成此操作: 通用标签
因此,情况是您希望C1和C2来自“功能”分支(分支点“ A”),但目前还没有。 通用标签
如上所述,将您带到交互式编辑器,在其中选择C1和C2的“拾取”行(如上所述)。保存并退出,然后它将继续进行重新设置,并为您提供分支“ temp”,以及在master + C1 + C2处的HEAD: 通用标签
然后,您只需将master更新为HEAD并删除temp分支,就可以了: 通用标签
我知道这个问题很旧,还有很多其他答案,但是我写了自己的脚本“ pmerge”来部分合并目录。这项工作仍在进行中,我仍在学习git和bash脚本。
此命令使用git merge --no-commit
,然后取消应用与提供的路径不匹配的更改。
用法:git pmerge branch path
示例:git merge develop src/
我还没有对其进行广泛的测试。工作目录中应没有任何未提交的更改和未跟踪的文件。 通用标签
git reset --soft branch
怎么样?我很惊讶没有人提及它。
对我来说,这是有选择地从另一个分支中选择更改的最简单方法,因为此命令将所有diff更改放入我的工作树中,因此我可以轻松选择或还原所需的内容。这样,我就可以完全控制已提交的文件。
一种用于按文件选择性合并/提交的简单方法:
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
如果您没有太多更改的文件,这将使您没有多余的提交。
1。暂时复制分支
遗传标记代码
2。重置为上次想要的提交
$ git checkout -b temp_branch
,其中$ git reset --hard HEAD~n
是您需要返回的提交次数
3。从原始分支中检出每个文件
遗传标记代码
现在,如果需要,您可以提交并强制推送(覆盖远程)。
两个分支的当前提交之间只有几个文件发生更改时,我将通过浏览不同的文件来手动合并更改。
git difftoll <branch-1>..<branch-2>
如果您只需要合并一个特定的目录并保留所有其他内容并保留历史记录,则可以尝试一下...在尝试之前,从target-branch
创建一个新的master
。
下面的步骤假定您有两个分支target-branch
和source-branch
,要合并的目录dir-to-merge
在source-branch
中。还要假设您在目标中还有其他目录,如dir-to-retain
,您不想更改和保留历史记录。另外,假设dir-to-merge
中存在合并冲突。
通用标签