当我遇到门上贴着 PUSH,我会先 PULL 一下,以避免冲突。
--佚名
熟悉 git
的人,常常不易发现它的新变化。如果排除 plumbing commands (译者注: git 中的底层命令),这些多数人都不了解的命令。这句话就更贴切了。挺意外的,我最近发现了高级命令列表中两个新加命令:
git restore
git switch
为什么要添加这两个命令,咱先看看我们的老朋友 git checkout
。
Checkout 是怎么回事
git checkout
是 git 众多让新手困惑的原因之一。因为它的作用依赖上下文。
人们大多使用它切换本地活动分支。准确来讲,是切换分支到某个 HEAD
指针。例如,当你在 main
分支时,你可以切换到 develop
分支。
git checkout develop
你也可以用某个 commit 的 HEAD
指针取代分支名(切换到所谓的 分离 HEAD
状态):
git checkout f8c540805b7e16753c65619ca3d7514178353f39`
如果你用文件名替换分支名或 commit 指针,事情就变的很奇怪,它会丢弃你对文件在工作区的修改,把文件还原到分支中的状态。
例如,你切换到 develop
分支,修改了 test.txt
文件,你可以将文件还原到当前分支最近一次 commit 的状态:
git checkout -- test.txt
为什么会这样
如果你第一次看到这种行为,你会认为它没法理解,为什么一个命令却有两种行为?原因比看上去微妙。如果你看 git documentation,就能看到,这还有个经常被忽略的参数:
git checkout <tree-ish> -- <pathspec>
<tree-ish>
是什么?它可以表示很多不同的东西,但最常用的是 commit hash
或分支名。默认值是当前分支,但它可以是任何其它分支或 commit。 所以如果你想把当前 develop
分支中的 test.txt
文件切换成 main
分支中的版本,你可以这么干:
git checkout main -- test.txt
这个搞明白了,事情就变得好理解了。当只提供一个分支名或 commit 作为 git checkout
的参数,它会修改所有文档到相应的版本,但如果你指定了文件名,它只会修改此文件到相应的版本。
欢迎新同学
即使读了前面的内容,你开始明白原来是这么回事,我们也必须承认它仍然会造成困扰,尤其是对新手。这就是为什么 2.23 of git,新加了两条命令替代老的 git checkout
(它仍然可用,但是建议刚用 git 的人们最好使用新命令)。如你所愿,它们分别实现了前面提到的两种行为,将 git checkout
一分为二。
Switch
它实现了 git checkout
切换分支的功能。所以你可以用它在分支 和 commit 之间切换。
git switch develop
使用 git checkout
你可以切换到某个 commit 将它转变为 分离 HEAD
状态,git switch 不能那样直接使用,你得加个 -d
参数:
git switch -d f8c540805b7e16753c65619ca3d7514178353f39
另一个不同之处在于,用 git checkout
加 -b
参数,你可以创建并切换到新分支:
git checkout -b new_branch
switch 命令也有这个功能,但你得用 -c
参数:
git switch -c new_branch
Restore
它实现了git checkout
命令还原文件的功能。你可以还原文件状态到某个指定版本(默认是当前分支)。
git restore -- test.txt
结语
这些命令仍在实验期,但不管你用与不用,它们就在那里,所以我非常希望每个人都开始使用它们,因为它们更容易理解,也能稍微减少 git 对新手的困扰。
更多详情请参考它们的 git documentation:
原作:https://www.banterly.net/2021/07/31/new-in-git-switch-and-restore/
参考
https://blog.youkuaiyun.com/yotcap/article/details/119348649?utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EOPENSEARCH%7Edefault-1.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EOPENSEARCH%7Edefault-1.control