`git branch -f <branch_name> <hash>` 和`git checkout <branch_name> 之间的区别; git 在干净的工作树下重置 --hard <hash>`?

Difference between `git branch -f <branch_name> <hash>` and `git checkout <branch_name>; git reset --hard <hash>` under a clean working tree?

到目前为止,我一直使用 git checkout <branch_name>; git reset --hard <hash> 将分支移回较早的提交。

然后我遇到了this question,但是答案和评论并没有很详细地解释它们之间的区别。

假设我有一个干净的工作树,

之间有什么内部差异
git branch -f <branch_name> <hash>

git checkout <branch_name>
git reset --hard <hash>

这些差异(如果有的话)对高级用法有什么微妙的影响吗?

主要区别在于 git branch -f <branchname> <commitref><branchname> 移动到指定的提交 而不会触及 HEAD索引 工作副本,而git checkout <branchname> && git reset --hard <commitref> 修改所有三个。

如果您想在不移动 HEAD 或修改当前工作树的情况下快速重新排列分支,那么 git branch -f 是一个很好的方法。如果您有 未提交的更改 ,它也会起作用,如果您使用 git checkout.

,这并不总是可行的

另一个差异与性能有关,但它仅与非常 的大型项目相关。
在这些情况下,使用 git checkoutgit reset --hard 修改您的工作树可能是一项 昂贵的操作 ,需要大量磁盘 I/O。另一方面,使用 git branch -f 只有 单个文件 将写入磁盘,即包含 <branchname> 引用的 <commithash> 的文件。