【问题标题】:git checkout -B without reset or alternatives?git checkout -B 没有重置或替代方案?
【发布时间】:2019-09-01 11:43:55
【问题描述】:

我想使用一个命令:

  1. 如果不存在,则创建一个新分支。
  2. Checkout 分支(如果存在且未对其进行任何修改)。

当前使用的git checkout -B branchname 违反了第二个要求,因为如果分支存在,它将分支重置为起点的HEAD。你知道checkout/workarounds/另一个满足这两个要求的命令的标志吗?

【问题讨论】:

  • 你可以用一个作为 Git 别名执行的 shell 管道(或者更好的 shell 函数)来解决它。
  • 似乎是唯一的选择...git checkout branchname,如果失败,git checkout -b branchname,正如 torek 在他的回答中建议的那样。
  • 确实如此。 git checkout branchname -- 2>/dev/null || git checkout -b branchname.

标签: git git-branch git-checkout


【解决方案1】:

没有一个 Git 命令可以做到这一点。

我推荐使用的命令序列是:

git checkout <name>

接着,如果失败:

git checkout -b <name> [<starting-point>]

(取决于你想要什么行为):

git checkout [-b <name>] --track <remote-tracking-name>

尖括号中的每一项代表您替换的内容(例如,&lt;name&gt; 可能是 feature/fast),方括号中的每一项代表可选的内容。

这里的主要问题是:

  • 如果您要创建新的分支名称,您必须选择这个新分支名称将识别的提交。您可以通过提供 &lt;starting-point&gt; 参数来选择特定的起点;如果你没有命名起点,Git 会假设你想要HEAD 作为起点。

    可以还选择新分支是否应该有一个上游集:这就是--track 的用途。但是请注意,在某些情况下,--track 是自动隐含的。

  • 如果您使用现有的分支名称,您——根据上面的陈述——不想更改它将识别的提交。 (此时,您无法选择设置/更改现有分支的上游,因此特定问题不会出现。)

现在让我们谈谈这里发生的所有附带问题。

有了-bgit checkout总是想新建一个分支

-b 和/或--track 标志告诉git checkout 它应该同时创建新分支然后切换到它。如果切换到将失败或确实失败,它应该回滚整个操作并且根本不创建新分支。所以这里一个起点。起点可能HEAD。因为分支是new,它还没有上游,但你可以告诉git checkout 设置上游,使用--track:@987654339 的参数@ 是上游的名称(应该是本地分支名称或远程跟踪名称,例如 origin/master)。

如果您提供-b 标志,您还提供了新的分支名称,因此这就是新分支的名称。如果省略-b 标志,则必须提供--track 和远程跟踪名称:在这种情况下,分支的名称是通过删除远程跟踪部分产生的名称,例如,origin/feature 变为@987654345 @,所以git checkout --track origin/featuregit checkout -b feature --track origin/feature意思一样。

如果您提供起点,Git 将需要检查该特定提交。起始点名称可以是远程跟踪名称(例如origin/masterorigin/feature)、提交哈希ID 或任何其他标识提交的名称。在大多数情况下,提供远程跟踪名称作为起点等同于提供 --track 参数,因此如果您不想想设置上游,请添加 --no-track .有关完整说明,请参阅 the git checkout documentation

没有-bgit checkout有时仍然会创建一个新分支

当您忽略-b 时,git checkout <em>name</em> 将首先测试 name 是否与某个现有分支匹配。如果是这样,操作的解码部分就完成了:Git 现在尝试检查该特定提交(由该分支标识),如果成功,则将您的 HEAD 附加到该分支,以便你现在在分支上。

但你可以写,例如:

git checkout feat/ure

如果您没有名为feat/ure 的分支。在这种情况下,Git 将枚举所有您的远程跟踪名称,例如origin/masterupstream/master 等。如果 正好一个 匹配 feat/ure 在剥离远程部分后,Git 假定您 打算 写:

git checkout --track origin/feat/ure

(或遥控器仍在其中的任何名称)。因此,这将创建 feat/ure,指向与origin/feat/ure 相同的提交,origin/feat/ure 作为新分支feat/ure 的上游设置。 p>

如果不存在 feat/ure 并且要么不存在,要么不存在或过多(两个或更多)远程跟踪 feat/ure 样式名称 - 例如,origin/feat/ureupstream/feat/ure 都存在 - 这个git checkout 将只是失败了,现在您必须诉诸-b 和/或--track 中的一个或多个。

另一种选择

如果您不喜欢这些替代方案,可以测试分支名称是否存在。为此,请让git rev-parse 翻译名称,并在其前面插入refs/heads/

git rev-parse --quiet --verify refs/heads/feat/ure

如果成功,它会打印出 refs/heads/feat/ure 解析到的哈希 ID,并以零状态退出。打印的哈希 ID 是 feat/ure 分支的尖端,因此存在。如果失败,它将不打印任何内容 (--quiet --verify) 并以非零状态退出,因此 feat/ure 不存在。您现在可以安全地请求create feat/ure — 也就是说,前提是没有其他人潜入您的存储库并在您查看退出状态并确定 @987654384 时创建了 feat/ure @ 不存在(但现在存在)。

在 shell 脚本中,这变成:

name=feat/ure
git rev-parse --quiet --verify refs/heads/$name >/dev/null && exists=true || exists=false
if $exists; then git checkout $name; else git checkout -b $name ...additional arguments; fi

当然,您可以将此脚本转换为 shell 别名或实际的 shell 脚本,随意调用它。添加足够的参数解析和错误处理来品尝。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-04-14
    • 2022-12-16
    • 2019-07-07
    • 2018-08-31
    • 2011-12-20
    • 2020-03-05
    • 1970-01-01
    相关资源
    最近更新 更多