git - git checkout -B 没有重置或替代方案?
问题描述
我想使用一个命令:
- 如果它不存在,则创建一个新分支。
- Checkout 分支,如果它存在且未对其进行任何修改。
当前使用git checkout -B branchname
违反了第二个要求,因为如果分支存在,它将分支重置HEAD
为起点。你知道任何标志checkout
/解决方法/另一个可以满足这两个要求的命令吗?
解决方案
没有一个 Git 命令可以做到这一点。
我推荐使用的命令序列是:
git checkout <name>
其次,如果失败:
git checkout -b <name> [<starting-point>]
或(取决于你想要什么行为):
git checkout [-b <name>] --track <remote-tracking-name>
其中尖括号中的每个项目代表您替换的东西(例如,<name>
可能是feature/fast
),方括号中的每个项目代表可选的东西。
这里的主要问题是:
如果您正在创建一个新的分支名称,您必须选择这个新分支名称将识别的提交。你通过提供一个论点来选择一个特定的起点
<starting-point>
;如果你没有指定起点,Git 会假设你想要HEAD
作为起点。您还可以选择新分支是否应该有一个上游集:这就是它的
--track
用途。但是,请注意,在某些情况下,--track
是自动隐含的。如果您使用现有的分支名称,则根据上面的陈述,您不想更改它将识别的提交。(此时,您没有为现有分支设置/更改上游的选项,因此特定问题从图片中消失。)
现在让我们谈谈这里发生的所有附带问题。
With -b
,git checkout
总是想创建一个新的分支
-b
and/or--track
标志告诉git checkout
它应该创建新分支然后切换到它。如果切换到将失败或确实失败,它应该回滚整个操作并且根本不创建新分支。所以这里有一个起点。起点可能是HEAD
。因为分支是新的,它还没有上游,但你可以告诉git checkout
设置上游,使用--track
:参数--track
是上游的名称(应该是本地分支名称,或者远程跟踪名称如origin/master
)。
如果您提供-b
标志,您也提供新的分支名称,因此这就是新分支的名称。如果省略该-b
标志,则必须提供--track
和远程跟踪名称:在这种情况下,分支的名称是通过删除远程跟踪部分产生的名称,例如origin/feature
become feature
,因此与 .git checkout --track origin/feature
的含义相同git checkout -b feature --track origin/feature
。
如果您提供起点,Git 将需要检查该特定提交。起始点名称可以是远程跟踪名称(例如origin/master
或origin/feature
)、提交哈希 ID 或任何其他标识提交的名称。在大多数情况下,提供远程跟踪名称作为起点等同于提供--track
参数,因此如果您不想设置上游,请添加--no-track
. 有关完整说明,git checkout
请参阅文档。
没有-b
,git checkout
仍然有时会创建一个新分支
当您省略时-b
,将首先测试名称是否与某些现有分支匹配。如果是这样,操作的解码部分就完成了:Git 现在尝试检查特定的提交(由该分支标识),如果成功,则将您附加到该分支,以便您现在在该分支上。git checkout name
HEAD
但是你可以写,例如:
git checkout feat/ure
当您没有名为feat/ure
. 在这种情况下,Git 将枚举您的所有远程跟踪名称,例如origin/master
、upstream/master
等。如果在剥离远程部分后恰好有一个匹配,Git 假定您打算编写:feat/ure
git checkout --track origin/feat/ure
(或者遥控器仍然在其中的任何名称)。因此,这将创建 feat/ure
,指向与新分支的上游设置相同的提交。origin/feat/ure
origin/feat/ure
feat/ure
如果 nofeat/ure
存在并且要么不存在,要么不存在或者太多(两个或更多)远程跟踪feat/ure
样式名称——例如,bothorigin/feat/ure
和upstream/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
不存在。您现在可以安全地请求创建 feat/ure
——也就是说,前提是没有其他人潜入您的存储库并在feat/ure
您查看退出状态并确定它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 脚本,随意调用它。添加足够的参数解析和错误处理来品尝。
推荐阅读
- python - 如何在 Python 类中正确使用泛型
- python - 使用 -argparse 指定参数时运行特定函数
- java - 在 Maven 依赖项中覆盖时覆盖 Spring Security 配置(HttpSecurity)
- python - 打印选择的 scipy.optimize.minimize 方法
- django - int() 参数必须是字符串、类似字节的对象或数字,而不是“列表”:Django 保存模型
- javascript - 如何在angular 2中找到excel文件的类型?要么是宏,要么不是
- laravel - Laravel 通过 Envoyer 部署到 Cpanel
- r - 访问 R 中的因子组件
- angular - 如何在 Angular 中对实时数据进行动态 API 调用
- python - 在 Raspbian Buster 上将 Python 3.7 降级到 3.5