Awesome Git

Awesome Git

絮叨一下

本文基于 git version 2.32.0

相较于 SourceTree 之类的可视化图形 git 管理软件, 本人更喜欢使用简单的命令去处理 git 相关的工作,原因也很简单:

  1. 装逼嘛🐶(开个玩笑~)
  2. 熟悉各个命令,我会很清楚各个文件、分支、commit的状态,比图形化的东西让我更加安心
  3. 配置好下文的各个命令别名,切换软件功夫,我可能已经完成对应的工作😁

🔥 当然了,平时 vscode 的 Source Control 我用的也很多,比如把文件从 Staged 状态切换到 Modified 状态。有一说一,这个比敲命令快而且便捷很多!


配置别名

.zshrc 中默认配置了 git 插件,内置了很多别名,但是并不适合我,别名当然要做适合自己的,起码不会忘不是😌!

先配置下git命令的别名
echo "alias g=git" >> ~/.zshrc
# config 的别名,便于配置和设置
git config --global alias.c config
git config --global alias.cg 'config --global'
git config --global alias.clg 'config --list --global'
git config --global alias.cll 'config --list --local'
自定义别名,复制到terminal跑一下即可
# 只 clone 某个分支/tag, 对于大型仓库很实用 g cloneb <brName/tagName> <url>
g cg alias.cloneb 'clone --single-branch --branch'

# 常规操作
g cg alias.st status
g cg alias.ad 'add -A'
g cg alias.cm 'commit -m'
g cg alias.ps push
g cg alias.pl pull

# ✅高频使用
# 当最新 commit 还未推到远程仓库前的三种常用操作:
# 1. 修改本次 commit message
g cg alias.cam 'commit --amend -m'
# 2. 在本次 commit 上追加变动,比如刚commit完,发现有个东西还没改
g cg alias.can 'commit --amend --no-edit'
# 3. 本次 commit 有些许问题, 放弃提交并将修改回退到工作区
g cg alias.back 'reset --soft HEAD^'

# ✅分支管理,也是高频使用的
# 如果能意识到【分支名/Tag名】只是一个特殊的commit指针而已,那你的 git 水平应该不会太差
# ⭐️ checkout 作用就是带着 HEAD 指针到处跑~(g ck - 快速切至上一个分支,同理 g merge -)
g cg alias.ck checkout                # 动起来~
g cg alias.cb 'checkout -b'           # 增
g cg alias.db 'branch -d'             # 删 本地
g cg alias.fdb 'branch -D'            # 删 本地(强制)
g cg alias.drb 'push origin --delete' # 删 远程
g cg alias.rb 'branch -m'             # 改
g cg alias.br branch                  # 查

# ✅回退管理
# 粗暴 工作区/暂存区全部重置
g cg alias.rs 'reset --soft'
# 温柔 工作区/暂存区全部保留
g cg alias.rh 'reset --hard'
# ⚠️ 注意,已经提交的commit,回退后需要 g ps -f 强制推送,团队成员要提前沟通好
# 或者可以使用 revert 来产生一个镜像的新 commit 来达到回退的目的
g cg alias.rv 'revert'

# 临时存储,适合开发过程中去修紧急bug‼️
g cg alias.sh stash
g cg alias.shp 'stash pop'

# 标签管理
# g tag <name>        # 增 一般都通过 npm version major|minor|patch 等命令自动生成标签
# g tag -d <name>     # 删 (删远程tag同删远程分支,侧面验证tag本质也就是commit指针罢了)
# g ps origin --tags  # 推送全部标签


# 🔨高级用法
# 1. 时光机: reflog & cherry-pick 结合使用
# 🐮reflog 能查看HEAD指针所有行走的轨迹,包括因reset舍弃的commit,这样,cherry-pick 就可以让你有后悔药了~
g cg alias.cp cherry-pick       # g cp <commit/branch-name>
# cp 区间 g cp  commitA..commitB  把区间 (A, B] 的 commit 都合进来,A 早于 B 的
# cp 区间 g cp  commitA^..commitB 把区间 [A, B] 的 commit 都合进来
# 如果是分支名则是把该分支最新commit合并(再次验证分支名本质也就是一个指针~)
# 2. 手术刀: rebase -i,可以实现 pick,drop,squash✅ 等操作
g cg alias.ri 'rebase -i'

# ✅log 美化
g cg alias.lg "log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit"
# 根据 commit 内容查找 commit
g cg alias.find "log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit --grep"
# 根据 commit 用户查找 commit
g cg alias.findby "log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit --author"

# 上述命令是平时高频使用的,还有很多命令没有记录,请自行查阅文档。

注意:reflog 查看的是本地历史,在别的电脑上是看不见的,同理如果电脑坏了,那么再也回不到未来了...另外,reflog 不会永远保存,Git 会定期清理那些 “用不到的” 对象,不要指望几个月前的提交还一直在那里。

新版本 git 增加了 switch/restore 命令, 真就一次没用过,可以自行研究🧐

配置用户

个人习惯是公司项目都单独配置,全局配置给自己用。

# 项目中配置
g c user.name 'Eric'
g c user.email '[email protected]'

# 全局配置
g cg user.name 'Eric'
g cg user.email '[email protected]'

HEAD 知多少

HEAD 是特殊的指针,默认指向的是当前最新的 commit,这个众所周知,但是 HEAD~HEAD^ 很多人就犯迷糊了。其实非常简单:

  • 紧跟着 HEAD 的 ~^ 都表示 HEAD 指针往后退一步,即指向父提交,有几个符号就代表往后移动几步

  • 但是当它们后面跟了数字,则含义就不一样了:

    • HEAD~3,表示往后退3步,与 HEAD~~~HEAD^^^ 等价
    • HEAD^3,表示往后退1步,并指向第3个父提交(是的父提交可能有多个,比如合并代码)

常见问题

git log 中文字符乱码

# vim ~/.gitconfig
export LC_ALL=zh_CN.UTF-8
export LANG=zh_CN.UTF-8
export LESSHARESET=utf-8

fatal: refusing to merge unrelated histories

g pl origin develop --allow-unrelated-histories

Git error on git pull (unable to update local ref)

g remote prune origin

参考