将更改从分支 A 应用到 B,而不合并或添加提交
Posted
技术标签:
【中文标题】将更改从分支 A 应用到 B,而不合并或添加提交【英文标题】:Applying the changes from branch A to B, without merging or adding commits 【发布时间】:2013-12-01 11:52:12 【问题描述】:我的情况是,我有一个分支,我在其中对构建过程(分支 A)进行了重大改进,而在另一个分支中,我正在开发一个不相关的功能(分支 B)。因此,现在当我在分支 B 上进行黑客攻击时,我想提取我在分支 A 中编写的内容,因为我想要更快、更轻松的构建。但是,我不想“污染”我的分支 B,只需将分支 A 中的更改添加到未暂存的更改中。
我尝试过的(站在branchB上时):
git merge --no-commit branchA
不起作用,因为它会将您置于合并中。如果没有,那就完美了。
git checkout branchA -- .
不起作用,因为它应用了 branchA..branchB 之间的更改,而不是更改 master..branchA。
还有什么?
编辑:是的,分支 A 上的更改已提交。在此示例中,只有一个具有构建改进的分支,但可能有多达 N 个具有构建改进的分支,我想在处理功能分支时应用它们。
【问题讨论】:
【参考方案1】:我只需要做一些类似的事情,并且能够通过在合并命令中添加 --squash
来修复它
git merge --no-commit --squash branchA
git reset HEAD # to unstage the changes
【讨论】:
这也应该有一个关于它做什么的解释性说明。它将分支 A 的更改差异分阶段到您当前的分支中 可以说我刚刚将 branchA 中的代码合并到 master 中,但我忘记了一些东西,想在此合并提交中添加更多代码/更改,而不显示为 git 历史中的另一个合并提交。这种方法行得通吗? @Sushmit 我认为你可以做一个git commit —amend
,它会将新的更改附加到最后一次提交,我只是不完全确定它是否适用于合并提交
我认为这里不需要 --no-commit ?应该是默认值。【参考方案2】:
cherry-pick -n
应该做你想做的事,但我不确定你为什么要将构建改进作为非分阶段的更改 - 这只会使一些事情变得更加困难(例如,将其他更改合并到修改后的文件,或重新设置任何内容)。
在此示例中,只有一个具有构建改进的分支,但可能有多达 N 个具有构建改进的分支,我想在处理功能分支时应用它们。
在这种情况下,我将创建一个新分支 C,您可以从 A 和 B(以及任何其他具有构建改进的分支)合并它。提交功能分支 B 上的更改,然后将它们合并到 C 分支,该分支现在包含构建改进和功能分支更改,因此您可以一起测试它们。如果您需要在适当的分支中进行更多更改,而不是 C,则合并到 C。因此,不要在 C 分支中更改任何内容,只需使用它来集成来自其他分支的更改。
这意味着您可以在分支 C 中使用 Git 的所有功能,而不是在脏树中处理未提交的更改。
【讨论】:
cherry-pick -n
的用例:我通过在随机位置添加大量内容来创建代码的工作副本。现在我想在提交到这个特性的分支之前清理我的代码。所以我切换到一个临时分支,提交所有更改。回到功能分支,cherry-pick
那个提交。有更好的方法吗?【参考方案3】:
我不确定我是否 100% 清楚地理解它,但就我而言,我刚刚在分支之间创建了差异补丁,然后将此补丁应用于 B 分支。
A分支内部:
git diff branchA..branchB > patch.diff
git apply patch.diff
【讨论】:
很好的答案,这特别有用,因为您使用了两点差异。我试图通过 PR 将分支 B 合并到 A,但它显示的差异是三点并且冲突不准确。 我正是需要这个,所以我创建了别名apply-diff-from = "!f() git diff ..$1 | git apply - ; ; f"
。也许这对某人有帮助。【参考方案4】:
您应该能够挑选提交(使用-n
以避免立即提交)。
【讨论】:
-n 不起作用。它说没有 -m 选项给定樱桃选择提交失败。【参考方案5】:我不确定我是否理解您的要求。
您可以运行合并,然后调用git reset HEAD~1
。
以下序列应在branchB
之上重播master
和branchA
之间的每个提交。将跳过已应用于 branchB
的提交。
# start from branchA
git checkout branchA
# create a temporary branch wip
git checkout -b wip
# use rebase to replay each commit between master and wip on branchB
git rebase --onto branchB master wip
# if you want to remove all the commit history and only keep the resulting diffs,
# use git reset
git reset branchB
# change the active branch
git checkout branchB
# remove temp branch
git branch -d wip
【讨论】:
这会将文件添加到我不想要的 git 暂存区。另外,只有当所有分支都从主分支上的同一个提交分支时,它似乎才能正常工作。否则,将引入不在 master..branchA 范围内的差异。 @BjörnLindqvist:如果您不希望在暂存区域中进行更改,请删除--soft
选项。你能画出你的分支是如何设置的图表吗?【参考方案6】:
从 git 2.23 版本开始,您可以使用git restore
精确地达到想要的结果。
git restore
提供选项来指定哪些文件将通过--staged
和--worktree
“恢复”。它还提供了一个选项来指定文件将通过--source
恢复到哪个状态,默认情况下它是工作副本并且可以接受任何git 对象。
因此问题可以表述为“将工作树中的所有文件恢复到分支A中所有文件的状态”,并且可以通过
git restore --source branchA --worktree .
可以将特定文件作为参数给出,而不是所有文件 (.
)。
【讨论】:
这是在所有情况下都能完全达到结果的最佳且唯一的答案(即使 branchA 和 branchB 不相关,这是我的情况)!非常感谢!!!以上是关于将更改从分支 A 应用到 B,而不合并或添加提交的主要内容,如果未能解决你的问题,请参考以下文章