【问题标题】:Git - How to selectively apply changes from one branch to another?Git - 如何选择性地将更改从一个分支应用到另一个分支?
【发布时间】:2014-04-17 12:56:37
【问题描述】:

是否可以使用 Git 选择性地将更改从一个分支应用到另一个分支?

更具体地说,我为 GitHub 使用公共 dev 分支和用于部署的私有 master 分支。当对一个分支进行更改时,它们将需要应用于另一个分支,但某些代码行需要保持不同。就我而言,它是一些 CSS 类和一个提要。

我是 Git 新手,但我已经进行了研究:

  • git merge --no-commit --no-ff 可以使用后跟git mergetool 在发生冲突时选择我想要的内容。问题是它只适用于 Git 无法自动合并的冲突,所以在我有机会使用我的合并工具之前,我想要保持不同的东西被替换了。

  • git difftool --cached 很有用,因为它可以让我看到差异,但我需要从那里复制我想要保留的内容并用文本编辑器手动替换它,因为我不能像我一样简单地选择和保存可以用mergetool。

  • git cherry-pick 似乎将一个指定的提交应用到另一个,但我想要保持不同的可能分散到不同的提交中,而这些提交可能不仅包括我想要保持不同的内容。除非我做出让我发疯的数百万次提交,否则我看不到这个工作。

还要明确一点,我不希望一个分支变成另一个,合并似乎是这种情况。 我想要两个具有各自差异的独立分支,并将更改从一个应用到另一个。

是否有更好的工作流程允许我通过应用更改并保留一些差异来保留开发和部署版本?如果可以找到解决方案,我不介意使用单独的存储库或不同的工具。

【问题讨论】:

  • 所以,基本上你有时可能只需要提交的一部分,这可能是从单个文件中的某些行到提交中的多个文件中的几个文件?
  • 合并时我需要保持几行不同的代码,例如一个分支中的白色背景和另一个中的黑色背景。我想合并同一文件中的其他更改,因此文件排除不能解决所有情况。

标签: git github workflow git-merge kdiff3


【解决方案1】:

我还发现了有关修补的信息:

创建补丁:git diff dev > master.patch

申请:patch < master.patch

【讨论】:

  • 谢谢你——点赞!但要注意一点——因为我的 git 配置为将丢弃的虚构目录名称 a/b/ 放在我的差异中,所以第二个命令对我来说略有不同:patch -p1 < master.patch
【解决方案2】:

我认为没有办法从同一个文件中选择提交的一部分。我想说你需要简单地重构你的代码来将这些部分移动到不同的文件中。

顺便说一句,如果您想从提交中获取一些文件,您可以将cherry-pick 与其他命令组合使用,如here 所述。

【讨论】:

  • 按照链接中的说明执行 git checkout -p branchname 就可以了!这使我可以从另一个分支以交互方式获得选择性更改,而无需合并。 Cherry-pick 也可以工作,但只会在每次提交时获得更改。
  • :/ 显然有一种方法——它可能并不容易。
【解决方案3】:

利用创建 git 分支成本低廉且不会影响工作目录的实际内容这一事实。

  1. 查看您的源分支dev
  2. 创建一个临时分支。它将指向 dev 所做的相同提交:checkout -b for_master

    大概,您知道(或可以轻松找出)dev 分支之前的哪个提交是您(部分)想要的更改之前的最后一个。在此示例中,假设该提交具有哈希 1457B4('last before',明白吗?)。

  3. 将您的 for_master 分支重置为该提交:git reset 1457B4。 (不要不要使用--hard开关!)

    现在,您有一个工作目录,其中包含 dev 中的所有更改,但从 for_master 分支的 POV 来看,这些更改未暂存且未提交(而 dev 分支仍指向提交记录所有的变化,所以工作还是安全的)。

  4. 使用交互式暂存(git add -p 和/或 git add -e),创建一个提交(或多个,如果您愿意),其中包含所有且您想要的更改申请您​​的master 分支。

    记下最后一次提交的哈希(或给它一个标签)。在这个例子中,我会说它的哈希是C0DA

  5. 查看master

  6. Cherry-pick 刚刚提交的代码:git cherry-pick 1457B4..C0DA

    (请注意,选择范围仅在 git 版本 1.7.2 之后可用。否则,您需要单独选择在步骤 4 中所做的所有提交。)

    另外请注意,当您选择一个范围时,该范围的开始是提交之前将实际选择的第一个提交。)

这个过程有点像所选答案中提到的使用git checkout -p 的逆过程。在共享一些代码但也有很多差异的两个分支之间创建cherry-pick-able 提交可能很有用(例如,在一个项目的两个主要版本之间),并且您不想花费很多时间在调用git checkout -p 时忽略不相关的文件。

就个人而言,我发现为同一个存储库使用两个不同的工作树目录(一个用于源分支,一个用于目标)并在两个命令 shell 之间切换,一个使用源分支目录(工作树)和另一个目的地。但是,如果您不习惯使用 git worktree 功能,那可能不适合您。

【讨论】:

  • 技术很好。帮助我从几个星期的混乱提交中重新安排了一系列单独的、范围明确的 PR,这些提交涵盖了单个分支中的多个功能(真遗憾 - 审查将是一场噩梦!)。谢谢!
猜你喜欢
  • 1970-01-01
  • 2020-06-03
  • 2022-11-15
  • 2019-03-17
  • 2015-01-01
  • 2016-06-15
  • 2010-10-01
  • 2013-06-08
相关资源
最近更新 更多