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

问题描述 投票:1303回答:25

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

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

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

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

我考虑过的方法:

  1. git merge --no-commit随后手动取消大量编辑,我不想在分支之间做出共同点。
  2. 手动将公共文件复制到临时目录中,然后git checkout移动到另一个分支,然后手动将临时目录复制到工作树中。
  3. 以上的变化。现在放弃exp分支,并使用另外两个本地存储库进行实验。这使得手动复制文件更加简单。

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

git git-merge git-cherry-pick git-patch
25个回答
9
投票

这不完全是你想要的,但它对我有用:

git checkout --patch <branch> <file path>

这是一些答案的混合。


8
投票

我有与上面提到的完全相同的问题。但我发现[alias]在解释答案时更清楚。

来自以上链接的命令:

.gitconfig

7
投票

我会做的

git diff commit1..commit2 filepattern | git-apply --index && git commit

这样,您可以限制来自分支的文件模式的提交范围。

被盗:.git/config


7
投票

我喜欢上面的'git-interactive-merge'答案,但有一个更简单。让git使用交互式的rebase组合为你做这个:

[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;' -"

所以情况是你想要来自'feature'分支的C1和C2(分支点'A'),但现在不需要其余的。

[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;' -"

如上所述,您将进入交互式编辑器,在该编辑器中为C1和C2选择“拾取”行(如上所述)。保存并退出,然后它将继续使用rebase并给你分支'temp'和HEAD在master + C1 + C2:

git mergetool-file <source branch> <file path>

然后你可以将master更新为HEAD并删除temp分支,你很高兴:

git checkout -p <branch> -- <paths> ...

6
投票

我知道这个问题很老,还有很多其他答案,但是我编写了自己的脚本'pmerge'来部分合并目录。这是一项正在进行的工作,我仍在学习git和bash脚本。

此命令使用this git blog,然后取消应用与提供的路径不匹配的更改。

用法:#You are in the branch you want to merge to git checkout <branch_you_want_to_merge_from> <file_paths...> 示例:http://www.gelato.unsw.edu.au/archives/git/0701/37964.html

我没有广泛测试过它。工作目录应该没有任何未提交的更改和未跟踪的文件。

      A---C1---o---C2---o---o feature
     /
----o---o---o---o master

5
投票

怎么样# git branch temp feature # git checkout master # git rebase -i --onto HEAD A temp ?我很惊讶没人提到它。

对我来说,这是从另一个分支中选择性地选择更改的最简单方法,因为,此命令放入我的工作树,所有差异更改,我可以轻松选择或还原我需要的那个。通过这种方式,我可以完全控制提交的文件。


4
投票

您可以使用 A---C1---o---C2---o---o feature / ----o---o---o---o-master--C1---C2 [HEAD, temp] 将给定的远程树读取或合并到当前索引中,例如:

# git branch -f master HEAD
# git branch -d temp

要执行合并,请改用git merge --no-commit

另见:git pmerge branch path


3
投票

一种通过文件选择性合并/提交的简单方法:

git merge develop src/


3
投票

如果您没有太多已更改的文件,这将使您无需额外提交。

1.暂时重复分支 #!/bin/bash E_BADARGS=65 if [ $# -ne 2 ] then echo "Usage: `basename $0` branch path" exit $E_BADARGS fi git merge $1 --no-commit IFS=$'\n' # list of changes due to merge | replace nulls w newlines | strip lines to just filenames | ensure lines are unique for f in $(git status --porcelain -z -uno | tr '\000' '\n' | sed -e 's/^[[:graph:]][[:space:]]\{1,\}//' | uniq); do [[ $f == $2* ]] && continue if git reset $f >/dev/null 2>&1; then # reset failed... file was previously unversioned echo Deleting $f rm $f else echo Reverting $f git checkout -- $f >/dev/null 2>&1 fi done unset IFS

2.重置为上次想要的提交 git reset --soft branch,其中read-tree是你需要返回的提交数量

3.从原始分支签出每个文件 git remote add foo [email protected]/foo.git git fetch foo git read-tree --prefix=my-folder/ -u foo/master:trunk/their-folder

现在,如果需要,您可以提交并强制推送(覆盖远程)。


2
投票

当两个分支的当前提交之间只有少数文件发生变化时,我通过浏览不同的文件来手动合并更改。

-m


2
投票

如果你只需要合并一个特定的目录,并保留其他所有内容并保留历史记录,你可以试试这个...在你实验之前创建一个新的How do I merge a sub directory in 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

以下步骤假设您有两个分支$ git checkout -b temp_branch$ git reset --hard HEAD~n,并且您要合并的目录n位于$ git checkout origin/original_branch filename.ext中。还假设您在目标中有其他目录,如git difftoll <branch-1>..<branch-2>,您不想更改并保留历史记录。此外,假设target-branch中存在合并冲突。

master
© www.soinside.com 2019 - 2024. All rights reserved.