gpt4 book ai didi

git - 在 git rebase 上自动 stash 保存/pop 更改?

转载 作者:行者123 更新时间:2023-12-02 04:18:24 26 4
gpt4 key购买 nike

我的 git 工作流程经常使用 rebase。我总是获取上游更改(我从中 fork 的主存储库)然后 merge 到我的分支,然后 rebase 以删除无用的(对我来说:D) merge 提交和树拆分。

这个工作流程中让我烦恼的一件事是:

$ git rebase upstream/master
Cannot rebase: You have unstaged changes.
Please commit or stash them.

$ git stash
Saved working directory and index state WIP on cc: abc1234 Merge remote-tracking branch 'upstream/master' into local_branch
HEAD is now at abc1234 Merge remote-tracking branch 'upstream/master' into local_branch

$ git rebase upstream/master
First, rewinding head to replay your work on top of it...
Applying: awesome code change

$ git stash pop

所以这里我们有 4 个命令,1=failed rebase,2=stash,3=rebase,4=stash pop。除了 3 之外的任何东西都只是无意识的工作。

所以,问题是:最推荐的自动化方法是什么?每次运行 git stash/rebase/pop 的别名?某些 git 配置强制 rebase stash 或将其视为另一个提交以在之后重新应用?还有什么?

最佳答案

编辑:从 Git 版本 1.8.4 开始,但在 Git 版本 2.0.1 中修复了一个重要的错误,git rebase现在有--autostash .您可以配置 git rebase使用 --autostash默认情况下也是如此,使用 git config --global rebase.autoStash true .请注意以下来自 the documentation 的句子:

However, use with care: the final stash application after a successful rebase might result in non-trivial conflicts.



(我仍然更喜欢提交。)

TL;DR 答案:只需提交(然后稍后取消)

它可以帮助您意识到 git stash真的只是 git commit (在更复杂的形式中,先提交索引,然后提交工作树——当你应用存储时,你可以保持索引和工作树的分离,或者将它们组合成一个工作树更改)。

stash 的特别之处在于它所做的提交——两个或者,与 -u-a ,甚至三个提交——以一种不寻常的形式(作为一个 merge 提交,这不是真正的 merge )并且没有放在任何分支上(相反,特殊的 refs/stash 引用用于保留和查找它们)。

由于它们不在分支上, rebase不接触它们,在您的工作流程中,它是 git stash pop将工作树更改带入您的新工作树。但是,如果您在分支上进行自己的(正常)提交,并重新设置并包含该提交,则此正常提交将与任何其他提交一起重新设置。稍后我们将解决最后一个问题;现在,让我们把它画出来,作为一系列做(或不)重新定位的提交:
... do some work ...
... make some commits ...
... more work ...
... do something that causes upstream/master to update, such as git fetch upstream
$ git stash

在这一点上,这是你所拥有的:
... - o - * - A - B - C     <-- HEAD=master
\ |\
\ i-w <-- stash
\
@-@-@ <-- upstream/master

在这里, A , B , 和 C是你的提交(我假设你已经做了 3 个),都在分支 master 上. i-w挂起提交 C是你的 stash,它不在分支上,但仍然是两个提交 "git stash bag"并且实际上附加到您的最新提交( C )。 @提交(可能只有一个)是新的上游提交。

(如果你没有提交,你的 stash-bag 挂起提交 * ,你当前的分支指向提交 * ,这样 git rebase 除了向前移动你当前的分支指针之外没有其他工作要做。一切在这种情况下,结果相同,但我假设有一些提交。)

现在你运行 git rebase upstream/master .这会将您的提交复制到新提交,并带有新 ID 和新父 ID,以便它们位于最后一个 @ 之上。 . stash-bag 不动,所以结果是这样的:
... - o - * - A - B - C     [abandoned, except for the stash]
\ |\
\ i-w <-- stash
\
@-@-@ <-- upstream/master
\
A'-B'-C' <-- HEAD=master

您现在使用 git stash pop ,它在工作树更改时恢复 i/w 内容,删除 stash标签(更准确地说, pop 它以便 stash@{1} ,如果存在,现在是 stash ,依此类推)。这释放了对原始 A - B - C 的最后引用链,意味着我们不需要 i-w位,这让我们重绘这个更简单:
... - @            <-- upstream/master
\
A'-B'-C' <-- HEAD=master plus work tree changes

现在让我们画出如果,而不是 git stash save 会发生什么,你只要做一个 git commit -a (或 git addgit commit 没有 -a)创建实际提交 D .你开始:
... - o-*-A-B-C-D   <-- HEAD=master
\
@-@-@ <-- upstream/master

现在你 git rebase upstream/master , 复制 A通过 D将它们放在最后一个 @ 的末尾,你有这个:
... - o-*-@-@-@     <-- upstream/master
\
A'-B'-C'-D' <-- HEAD=master

唯一的问题是你有这个不需要的额外提交 D (好吧, D' 现在),而不是未提交的工作树更改。但这与 git reset 无关紧要。退一步提交。我们可以使用 --mixed重置—默认值—也重新设置索引(暂存区),以便“取消添加”所有文件,或者如果您希望它们保留 git add -ed, 一个 --soft重启。 (都不会影响生成的提交图,只有索引状态不同。)

git reset --mixed HEAD^   # or leave out `--mixed` since it's the default

这是它的样子:
... - o-*-@-@-@     <-- upstream/master
\
A'-B'-C' <-- HEAD=master
\
D' [abandoned]

您可能认为这效率低下,但是当您使用 git stash 时您实际上至少进行了两次提交,然后在您 git stash pop 时放弃这些提交。他们。真正的区别在于,通过进行临时的、非公开提交的提交,您可以自动重新设置这些提交。

不要害怕临时提交

git 有一个通用规则:进行大量临时提交,以便在进行时保存您的工作。您以后可以随时将它们 rebase 。也就是说,而不是这样:
... - * - A - B - C   <-- mybranch

哪里 A , B , 和 C是完美的和最终的提交顶部提交 * (来自其他人或较早发表的内容),请执行以下操作:
... - * - a1 - a2 - b1 - a3 - b2 - a4 - b3 - c1 - b4 - c2 - c3

哪里 a1是在 A 处的初始刺, a2修复了 a1 中的错误, b1是对 b 的初步尝试工作, a3来自意识到 b1需要 A毕竟要与众不同, b2修复了 b1 中的错误, a4修复了 a3 中的错误的更改为 a2 , 和 b3是什么 b1应该已经完成​​;然后 c1是在 C 的初步尝试, b4是对 b1 的另一个修复, c2是一种细化,等等。

假设在 c3 之后你认为它基本上已经准备好了。现在你运行 git rebase -i origin/master或者别的什么,洗牌 pick获取行 a1通过 a4整理好, b1通过 b4按顺序,和 c1通过 c3有序,让 rebase 运行。然后修复所有冲突并确保内容仍然正确,然后运行另一个 git rebase -i折叠所有四个 a版本为 A , 等等。

当你全部完成后,看起来你创造了一个完美的 A第一次(或者可能使用 a4 或其他一些,这取决于您保留哪些提交,放弃哪些提交以及您是否在事物中重新设置任何时间戳)。其他人可能不想或不需要看到你的中间工作——尽管你可以保留它,而不是组合提交,如果这有用的话。同时,您永远不需要必须重新设置未提交的内容,因为您只提交了部分内容。

在一行提交文本中给出这些提交名称确实有帮助,这将指导您以后的 rebase 工作:

git commit -m 'temp commit: work to enable frabulator, incomplete'

等等。

关于git - 在 git rebase 上自动 stash 保存/pop 更改?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27116671/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com