【问题标题】:Applying the changes from branch A to B, without merging or adding commits将更改从分支 A 应用到 B,而不合并或添加提交
【发布时间】: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 个具有构建改进的分支,我想在处理功能分支时应用它们。

【问题讨论】:

    标签: git merge branch


    【解决方案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 之上重播masterbranchA 之间的每个提交。将跳过已应用于 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 不相关,这是我的情况)!非常感谢!!!
    猜你喜欢
    • 2016-03-07
    • 2020-12-11
    • 2020-08-09
    • 1970-01-01
    • 2022-01-23
    • 2016-11-20
    • 2018-10-24
    • 1970-01-01
    • 2015-10-02
    相关资源
    最近更新 更多