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

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

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

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

我考虑过的方法:

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

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


当前回答

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

如果所需的更改不在单个提交中,则使用此处显示的方法将提交拆分为单个提交。大致来说,您使用git rebase-i获取原始提交以进行编辑,然后使用git reset HEAD^选择性地还原更改,然后使用git commit将该位提交为历史中的新提交。

Red Hat Magazine还有另一个很好的方法,他们使用git-add——补丁或者可能是git-add,如果你想将不同的更改拆分到一个单独的文件中(在该页面中搜索“拆分”),则可以只添加大块的一部分。

拆分更改后,您现在可以随意选择所需的更改。

其他回答

还有另一条路要走:

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.

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

如果所需的更改不在单个提交中,则使用此处显示的方法将提交拆分为单个提交。大致来说,您使用git rebase-i获取原始提交以进行编辑,然后使用git reset HEAD^选择性地还原更改,然后使用git commit将该位提交为历史中的新提交。

Red Hat Magazine还有另一个很好的方法,他们使用git-add——补丁或者可能是git-add,如果你想将不同的更改拆分到一个单独的文件中(在该页面中搜索“拆分”),则可以只添加大块的一部分。

拆分更改后,您现在可以随意选择所需的更改。

我想要的是:在一个新的分支中,以交互方式从一个分支(它有几个混乱的提交)中选择一个大块的提交。

如果diff中有任何二进制文件,gitdiff+gitapply将无法工作。

我的方法:

# New branch from a clean starting point, e.g. master
git checkout new-clean-branch origin/master

# Get all changes from the messy branch
# (quote the star so your shell doesn't expand it)
git checkout messy-branch -- '*'

# Unstage ("un-add") everything
git restore --staged .

# Interactively add hunks to be staged for commit
git add -p

tl;博士

git checkout source_branch -- path/to/file
# resolve conflicts if any
git commit -am '...'

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

摘要:

检查要合并的分支的路径,$git签出source_branch--<paths>。。。提示:它也可以像链接文章中看到的那样,不使用“--”。或者选择性地合并大块$git checkout-p source_branch--<paths>。。。

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

    $ git reset <paths>...
    $ git add -p <paths>...

最后提交$gitcommit-m“'合并'这些更改”

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

1.临时复制分支$git结帐-b temp_branch

2.重置为上次所需提交$git reset--hard HEAD~n,其中n是需要返回的提交次数

3.从原始分支签出每个文件$git签出原点/original_branch文件名.ext

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