提交到 git 中的替代分支(保持工作副本不变)

Commit to alternative branch in git (leaving working copy unmodified)

我在分支机构工作 topic。我做了一些更改,我想在侧分支 attempt1 上提交。提交这些更改后,我想从我当前的状态 继续 topic(而不是回到 topic 的最后一次提交)。

这样做的原因是,在更改足以进入已发布的分支之前我需要做更多的工作(我定期推送 topic),但我想保存一份副本当前状态,以防我搞砸返工。我不想在执行此操作时更改我的工作副本。我希望最终得到一个空索引。

请注意,我想保留 attempt1 一段时间 — 这不仅仅是一个非常临时的提交,我将在几分钟后变基。有时我决定在 topic 上改变我的方法,同时在 attempt1 上寻求替代方法。我想创建一个分支,而不仅仅是隐藏一个提交。

另外,我正在寻找一些强大的东西,所以交互式变基已经过时了。暂时提交 topic 然后将提交移动到一个新分支就可以了,只要我可以在不修改工作副本的情况下做到这一点。

在图形方面,我处于状态

HEAD
 |
 v
 A  topic

有未提交的更改,我想

HEAD
 |
 v
 A  topic
  \
   B  attempt1

具有与 B 相同的未更改工作副本。

然后我可以 git checkout -b attempt1git add 个新文件和 git rm 个删除的文件)git commit -a。但是,我如何在不修改工作树的情况下切换回 topic

基本上,我该怎么做

git commit --to-alternate-branch=attempt1

或(在创建并提交到 attempt1 之后)

git checkout --do-not-modify-working-tree topic

git stash --no-revert(后跟 git branch attempt1 stash@{0}),或其他什么?我能想到的所有组合在某些时候都会弄乱我的工作副本。

使用git

按照您在问题中描述的方式(即像往常一样)创建新分支 attempt1。那么:

git checkout topic
git checkout attempt1 .

git help checkout 显示了这个变体的确切作用。这将使您的新索引类似于 attempt1,但如果您愿意,您可以轻松取消暂存。

请注意,如果您的原始状态同时包含已暂存和未暂存的更改,则此区别将丢失。

不使用 git

假设您的工作目录名为 src...

cd ..
cp -r src src2  
cd src2
git branch attempt1
git add ... 
git commit
git push origin attempt1
cd ..
rm -rf src2

有点像大锤,但它可以满足您的要求。

如果您没有 origin 或不想推送到那里,那么不要推送:

cd ../src
git remote add tmp PATHTOSRC2
git fetch tmp
git branch attempt1 tmp/attempt1
git remote del tmp
rm -rf ../src2

根据您对 "why" 的描述,我可以告诉您有一个更简单的方法。如果您决定只是真的想使用临时分支,那么您当然可以。

现在,AnoE 建议的方法通常会起作用,但可能无法正确反映删除。有多种方法可以为此调整程序,但我讨厌尝试跟踪它们;所以你可以使用 stashes。

git stash
git checkout -b attempt1
git stash apply
git commit
git checkout topic
git stash pop

但是就像我说的,这真的是在重新发明轮子。您不需要分支来存储可以返回的状态。你只需要一个提交

git commit

并且您会争辩说您永远不想推送提交;这没问题。如果你完成了你的工作并且很好,

git rebase -i

您会看到一个提交列表,每个都标记为 pick;这是 git rebase 的 TODO 列表。找到您不想要的提交,并将 next 提交的命令更改为 squash。因此,例如,TODO 列表显示为

pick 00000001 first attempt
pick 00000002 here's a commit I want to push

你改成

pick 00000001 first attempt - don't push this
squash 00000002 but here's a commit I want to push

和 "temporary" 提交将从您的分支历史记录中删除。是的,这是一个历史重写,但是你在 共享分支之前这样做 (这就是重点)所以没关系。

确保已使用 git add 添加了任何新文件,并且已使用 git rm 声明了已删除的所有文件。那么:

git commit -a
git branch attempt1
git reset HEAD^

这会在当前分支上创建一个提交,然后撤消该提交(混合重置会更改当前分支指向的位置,但不会修改工作副本)。在两者之间,创建一个新分支,其提示是该提交,而不切换到该分支。

索引最终为空。如果要在索引中进行更改,请使用软重置 (git reset --soft HEAD^)。