你问题的前提是错误的:
一个简单的git checkout <argument> 是不可能的,因为它不会像git checkout origin/<argument> 那样检查远程分支。
了解关于 Git 的几个相互关联的事情很重要:
- 总是——嗯,几乎总是——当前提交,您可以使用单词
HEAD 来查找。
- 当前分支并不总是存在的,但如果有,它就是一个分支名称,即一个全名格式为
refs/heads/<em>name</em> 的引用。同一个词—HEAD,全部大写,找到该分支名称。如果没有当前分支名称,Git 将其称为分离的 HEAD。
-
远程跟踪名称,例如
origin/master,不是分支名称。它的完整形式以refs/remotes/ 开头,而不是refs/heads/。
- 如果您告诉
git checkout 签出一个提交,但用 branch 名称以外的其他名称来标识它,Git 将——如果签出成功,即——生成 detached第 2 点中描述的 HEAD 状态。(您也可以使用git checkout --detach 生成具有分支名称的相同状态。)
上面第 4 点的结果是 git checkout origin/<em>name</em> 导致分离的 HEAD,与 git checkout <em>hash-ID</em> 的方式相同。
这意味着你的脚本可以只使用git checkout <argument>,因为它会做同样的事情——产生一个分离的HEAD——如果参数是一个哈希ID或者它是一个远程跟踪名称,比如origin/develop。
但是,请注意,如果我们将此语句更改为:
简单的git checkout <argument> 是不合适的,因为它不会像git checkout <argument minus the leading origin/ part> 那样首先基于现有的远程跟踪名称创建然后签出本地分支。
我们得到了一个真实的陈述:git checkout develop 将创建一个名为 develop 的新(本地)分支使用名称 origin/develop(当然,前提是,那个本地的develop 还不存在)。但是,在这里只允许<argument> 并让用户提供develop 作为名称并没有明显的问题:
#! /bin/sh
git fetch && git checkout "$@"
例如。
旁注
这里的第 1 点和第 2 点有一个有趣的结果,即询问 目前HEAD 的值是多少实际上是在询问两个不同中的一个问题:
-
HEAD 是否附加到分支?如果有,是哪个分支?
- 当前提交的哈希 ID 是多少?
git symbolic-ref HEAD 命令只回答第一个问题; git rev-parse HEAD 主要回答第二个,但也可以被告知也回答第一个。
在上面的第 1 点中,几乎出于特定原因。想象一下,您刚刚创建了一个新的、完全空的存储库。 此存储库中没有提交,那么当前提交是哪个提交?
这种情况对于 Git 来说是有问题的。你在一个分支上,即master,不存在。 Git 将此称为 孤立分支 或 尚未创建的分支(取决于 Git 的哪个部分正在执行调用)。 Git 处理这个问题的方式是将分支的 name 存储到 .git/HEAD 中,而不是在参考数据库中实际创建 分支本身。当您进行新提交时,that 会自行创建分支,现在问题已解决:您在分支上,它标识了刚刚进行的一个新提交,即当前提交,所以HEAD 命名当前提交和当前分支。
(Git 可以根据需要重新创建这种稍微有点苦恼的情况,使用git checkout --orphan,它将新分支的名称写入HEAD,而不实际创建新分支。)