我目前可以通过以下三个步骤完成:
- 使用
git reset HEAD <file>...
取消暂存 - 切换到分支
git checkout [-b] <branchname>
- 再次暂存文件
git add <file>...
是否有更好的方法来移动已暂存的更改?
我目前可以通过以下三个步骤完成:
git reset HEAD <file>...
取消暂存git checkout [-b] <branchname>
git add <file>...
是否有更好的方法来移动已暂存的更改?
Edmundo's answer是正确的,但它需要一些关于为什么它是正确的细节。
这里有两种情况值得注意:
从你现在所在的提交创建一个新分支非常容易:
$ git checkout -b newbranch
... continue working; git add and/or git commit as usual ...
git checkout -b
步骤只要新分支本身没有问题(有一个有效的名称且不与现有名称重复),就永远不会失败。
移动到其他已存在的分支可能是非常简单的:
$ git checkout otherbranch
... continue working ...
如果失败了,您至少需要进行一次提交。您可以将此提交作为普通提交进行,然后将其复制到新分支并从当前分支中删除;或者您可以使用git stash
,它实际上会进行两个提交。只是这两个提交不在任何分支上,这使得git stash apply
可以在任何地方重新应用这些提交。(使用git stash pop
就像是说git stash apply && git stash drop
,即应用然后,如果Git认为这样做没问题-无论是否真的确实很好-丢弃存储。我建议将这两个操作拆分开来,以便您可以检查它是否正常,尽管通常情况下确实正常,最终这通常是相当微小的。)git stash save --untracked
或git stash save --all
,它实际上会进行三个提交。您可能不想要三个提交形式,因为它更加棘手。HEAD
)。也就是说,您运行:git checkout <branch-name-or-commit-hash-or-similar>
当你使用git checkout
命令切换分支时,当前工作目录和暂存区会被重置以匹配你切换到的提交(也就是HEAD
所指向的提交)。比如使用git checkout master
切换到master分支。
如果此时你没有对工作目录和暂存区进行修改,那么你可以随意使用git checkout
命令切换到其他提交,如git checkout develop
。Git可以抛弃掉暂存区和工作目录中的版本,因为它们与你之前检出的提交相同。如果Git删除了一个README
文件,甚至是你整个的工作区,也没关系,它们仍然存在于另一个提交中,即master
分支的tip提交。当你需要它们时,只需再次使用git checkout master
命令即可。
但这不是你在这里关心的情况。在这里,你已经修改了一些文件,甚至可能已经用git add
将它们加入了暂存区。但是git add README
只是将文件从工作目录复制到暂存区。这意味着暂存区和工作目录中的README
版本相互匹配,但它们都不与HEAD
(即当前)提交匹配。
假设HEAD
是develop
分支的tip提交,而你应该在feature
分支上进行操作。你想使用git checkout feature
命令切换到feature
分支。但是README
会发生什么情况呢?你修改了它,甚至可能已经将其添加到了暂存区中。
实际上,Git很“懒惰”。如果现在运行git checkout feature
命令把HEAD
提交移动到feature
分支的tip提交,Git必须要做一些工作。这可能包括删除当前的README
文件,并用feature
分支的tip提交中的文件替换它。
也许,仅仅是也许,在feature
的顶级提交中,有与develop
的顶级提交相同的README
文件。如果是这样,Git就可以偷懒!Git只需要让原来的README
保留在索引/暂存区和/或工作树中,不用费心去删除它们。它可以将修改后的README
留在它现在所在的任何位置。这正是Git所做的。
如果Git不能对文件偷懒,它会进行检查。如果您在索引和/或工作树中拥有的文件与您正在尝试移动的HEAD
提交中的文件不匹配,则git checkout feature
失败。(请参见git read-tree文档及其列表-哎呀!-“两个树合并”的21种可能情况,以了解确切的成功和失败情况。但大多数情况下,您不必关心所有这些:如果成功,那就好了;如果失败,您必须提交或存储)。
这就是为什么git checkout -b newbranch
总是成功的原因:它使用该分支名称创建新分支,该分支名称指向当前(HEAD
)提交。然后它从HEAD
提交切换到…好吧,本身。没有什么需要切换的。懒惰的步骤适用于每个文件:不必更改任何文件,因此也不会更改任何文件,因此git checkout -b
可以工作。
这就是为什么git checkout -b otherbranch
有时会成功的原因:它需要从HEAD
提交切换到otherbranch
的顶部。如果该提交具有某些不同的文件,Git将不得不删除索引/暂存区和工作树中现在存在的文件,并用来自otherbranch
顶部的版本替换它们。只有当索引/暂存区和工作树中现在存在的版本与HEAD
提交中的版本匹配时才允许这样做。
git checkout
允许使用-m
来进行合并(提交;它也允许在文件上使用-m
,但这些工作方式不同)。本质上,git checkout
运行git read-tree
来执行两种或三种合并。这些规则在git read-tree
文档中详细说明。即使进行了一些压缩,对于两个树的“合并”,也有21行规则! - torek仅检查您想把它们移动到哪里就足够了。Git会进行检查,以查看已暂存的更改是否可以在您检出的点上应用而不发生冲突。另一个简单的技巧是将更改隐藏起来,然后检出分支,然后再恢复更改。
git stash
git checkout someBranch
git stash pop