了解一下 Git 的一些现代指令和特性?

你应该了解和运用的现代 Git 指令和功用

现在现已不是 2005 年了, git供给的不仅仅是add, commit, pushpull. 让咱们来讨论一下你应该知道的一切新的, 现代化的 git 指令吧.

咱们一切的软件工程师每天都在运用git, 但大多数人只接触过add, commit, pushpull等最基本的指令, 就像还在2005年一样.

但是, Git 从那时起引进了许多功用, 运用这些功用能够让你的日子变得更轻松, 所以让咱们来探索一些最近增加的现代 git 指令, 你应该了解它们.

switch

从 2019 年开端, 或许更精确地说, 从 Git 2.23 版别开端, 咱们能够运用 git switch 来切换分支:

git switch other-branch
git switch -  # Switch back to previous branch, similar to "cd -"
git switch remote-branch  # Directly switch to remote branch and start tracking it

这很帅, 但咱们从一开端就用 git checkout 在 Git 中切换分支了, 为什么还需求一个单独的指令呢? git checkout是一个十分通用的指令–它能够(除其他外)检出或康复特定文件, 乃至特定提交, 而新的 git switch 切换分支. 此外, switch还会履行一些checkout不履行的额外的合理性查看, 例如, 如果switch会导致本地改动丢掉, 那么它就会中止操作.

restore

Git 2.23 版新增的另一个子指令/功用是 git restore, 咱们能够用它把文件康复到前次提交的版别:

# Unstage changes made to a file, same as "git reset some-file.py"
git restore --staged some-file.py
# Unstage and discard changes made to a file, same as "git checkout some-file.py"
git restore --staged --worktree some-file.py
# Revert a file to some previous commit, same as "git reset commit -- some-file.py"
git restore --source HEAD~2 some-file.py

上面代码段中的注释解释了各种 git restore 的作业原理. 一般来说, git restore取代并简化了git resetgit checkout的一些用例, 由于它们现已是超载的功用了. 关于 revert, restorereset 的比较, 请参阅 本文档部分.

sparse-checkout

Next one isgit sparse-checkout, a little more obscure feature that was added in Git 2.25, which was released on January 13, 2020.

下一个是 git sparse-checkout, 这是 2020 年 1 月 13 日发布的 Git 2.25 中新增的一个不起眼的功用.

比方说, 你有一个大型的单库房(monorepo), 其间的微服务被分隔到各个目录中, 由于版别库太大, checkoutstatus之类的指令履行起来十分慢, 但或许你真的只需求处理单个子树/目录. 那么, git sparse-checkout 来解救你了:

$ git clone --no-checkout https://github.com/derrickstolee/sparse-checkout-example
$ cd sparse-checkout-example
$ git sparse-checkout init --cone  # Configure git to only match files in root directory
$ git checkout main  # Checkout only files in root directory
$ ls
bootstrap.sh  LICENSE.md  README.md

$ git sparse-checkout set service/common

$ ls
bootstrap.sh  LICENSE.md  README.md  service

$ tree .
.
├── bootstrap.sh
├── LICENSE.md
├── README.md
└── service
    ├── common
    │   ├── app.js
    │   ├── Dockerfile
    ... ...

在上面的比如中, 咱们首要克隆了库房, 但并没有实际查看一切文件. 然后咱们运用git sparse-checkout init --cone来配置git只匹配库房根目录下的文件. 这样, 在运行checkout后, 咱们就只有 3 个文件, 而不是整棵树了. 要下载/检出特定目录, 咱们运用git sparse-checkout set ....

如前所述, 这在本地处理庞大的库房时十分便利, 但在 CI/CD 中, 当你只想构建/布置 monorepo 的一部分, 而不需求检出一切文件时, 这对进步流水线性能同样有用.

有关sparse-checkout的具体介绍, 请参阅这里.

worktree

一个人或许需求一起在单个运用(库房)中处理多个功用, 或许当你正在处理某个功用恳求时出现了一个重要的 bug, 这种状况并不少见.

在这种状况下, 要么你必须克隆多个版别/分支的版别库, 要么你需求躲藏/丢掉你其时正在处理的内容. 2018 年 9 月 24 日发布的 git worktree 就是处理这些状况的办法:

git branch
# * dev
# master
git worktree list
# /.../some-repo  ews5ger [dev]
git worktree add -b hotfix ./hotfix master
# Preparing worktree (new branch 'hotfix')
# HEAD is now at 5ea9faa Signed commit.
git worktree list
# /.../test-repo         ews5ger [dev]
# /.../test-repo/hotfix  5ea9faa [hotfix]
cd hotfix/  # Clean worktree, where you can make your changes and push them

该指令允许咱们一起签出同一版别库的多个分支. 在上面的比如中, 咱们有 2 个分支devmaster. 假定咱们正在dev分支中开发功用, 但有人告诉咱们要进行紧迫 bug 修正. 与其将更改存储起来并重置分支, 不如在 master 分支的 ./hotfix 子目录下创立一个新的Worktree. 然后, 咱们就能够移动到该目录, 进行修改, 推送并回来原始Worktree.

更具体的介绍请参阅本文.

bisect

最终但并非最不重要的是git bisect, 它并不新鲜(Git 1.7.14, 2012 年 5 月 13 日发布), 但大多数人只运用 2005 年左右的git功用, 所以我觉得仍是值得展示一下.

正如文档页所描述的那样: git-bisect – 运用二进制搜索查找引进错误的提交:

git bisect start
git bisect bad HEAD  # Provide the broken commit
git bisect good 479420e  # Provide a commit, that you know works
# Bisecting: 2 revisions left to test after this (roughly 1 step)
# [3258487215718444a6148439fa8476e8e7bd49c8] Refactoring.
# Test the current commit...
git bisect bad  # If the commit doesn't work
git bisect good # If the commit works
# Git bisects left or right half of range based on the last command
# Continue testing until you find the culprit
git bisect reset  # Reset to original commit

首要, 咱们运用 git bisect start清晰启动分段会话, 然后供给不生效的提交(很或许是HEAD)和最终一次已知的作业提交或符号. 有了这些信息, git 就会查看出介于 “bad”“good” 提交之间的一个提交. 这时, 咱们需求测验该版别是否有 bug, 然后运用git bisect good来告诉git该版别有用, 或运用git bisect bad来告诉 git该版别无效. 咱们不断重复这个过程, 直到没有提交了, git 就会告诉咱们哪个提交引进了问题.

我推荐你去看看文档那里还有更多关于git bisect 的选项, 包括可视化, 重放或跳过提交.

总结一下

如果你搜索一些与 git 相关的问题, 你很或许会在 StackOverflow 上找到有几千个向上投票的答案的问题. 虽然这个答案很或许依然有用, 但很或许现已过期, 由于它是 10 年前写的. 因此, 或许还有更好, 更简略, 更简单的办法. 所以, 当遇到一些git问题时, 我建议查看git文档, 了解更多最新的指令, 这些指令都有许多很好的示例, 或许阅读man页面, 了解多年来增加到老指令中的许多标志和选项.