前言

使用 Git 作为代码版本管理,早已是现在开发工程师必备的技能。可大多数工程师还是只会最基本的保存、拉取、推送,遇到一些commit管理的问题就束手无策,或者用一些不优雅的方式解决。

本文分享我在开发工作中实践过的实用命令。这些都能够大大提高工作效率,还能解决不少疑难场景。下面会介绍命令,列出应用场景,手摸手教学使用,让同学们看完即学会。

[官方文档]:https://git-scm.com/docs

stash

描述

当您想记录工作目录和索引的当前状态,但又想返回一个干净的工作目录时,请使用git stash。该命令将保存本地修改,并恢复工作目录以匹配头部提交。
stash 命令能够将还未 commit 的代码存起来,让你的工作目录变得干净。

应用场景

我猜你心里一定在想:为什么要变干净?

应用场景:某一天你正在 feature 分支开发新需求,突然产品经理跑过来说线上有bug,必须马上修复。而此时你的功能开发到一半,于是你急忙想切到 master 分支,因为当前有文件更改了,需要提交commit保持工作区干净才能切分支。由于情况紧急,你只有急忙 commit 上去,commit 信息也随便写了个“暂存代码”,于是该分支提交记录就留了一条黑历史(真人真事,看过这种提交)…

命令使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 保存当前未commit的代码
git stash

# 保存当前未commit的代码并添加备注
git stash save "备注的内容"

# 列出stash的所有记录
git stash list

# 删除stash的所有记录
git stash clear

# 应用最近一次的stash
git stash apply

# 应用最近一次的stash,随后删除该记录
git stash pop

# 删除最近的一次stash
git stash drop

reset –soft

描述

完全不接触索引文件或工作树(但会像所有模式一样,将头部重置为)。这使您的所有更改的文件更改为“要提交的更改”。
回退你已提交的 commit,并将 commit 的修改内容放回到暂存区。
一般我们在使用 reset 命令时,git reset –hard 会被提及的比较多,它能让 commit 记录强制回溯到某一个节点。而 git reset –soft 的作用正如其名,–soft (柔软的) 除了回溯节点外,还会保留节点的修改内容。

应用场景

回溯节点,为什么要保留修改内容?

应用场景1:有时候手滑不小心把不该提交的内容 commit 了,这时想改回来,只能再 commit 一次,又多一条“黑历史”。

应用场景2:规范些的团队,一般对于 commit 的内容要求职责明确,颗粒度要细,便于后续出现问题排查。本来属于两块不同功能的修改,一起 commit 上去,这种就属于不规范。这次恰好又手滑了,一次性 commit 上去。

命令使用

1
2
# 恢复最近一次 commit
git reset --soft HEAD^

reset –soft 相当于后悔药,给你重新改过的机会。对于上面的场景,就可以再次修改重新提交,保持干净的 commit 记录。

以上说的是还未 push 的commit。对于已经 push 的 commit,也可以使用该命令,不过再次 push 时,由于远程分支和本地分支有差异,需要强制推送 git push -f 来覆盖被 reset 的 commit。

还有一点需要注意,在 reset –soft 指定 commit 号时,会将该 commit 到最近一次 commit 的所有修改内容全部恢复,而不是只针对该 commit。

cherry-pick

描述

给定一个或多个现有提交,应用每个提交引入的更改,为每个提交记录一个新的提交。这需要您的工作树清洁(没有从头提交的修改)。
将已经提交的 commit,复制出新的 commit 应用到分支里。

应用场景

commit 都提交了,为什么还要复制新的出来?

应用场景1:有时候版本的一些优化需求开发到一半,可能其中某一个开发完的需求要临时上,或者某些原因导致待开发的需求卡住了已开发完成的需求上线。这时候就需要把 commit 抽出来,单独处理。

应用场景2:有时候开发分支中的代码记录被污染了,导致开发分支合到线上分支有问题,这时就需要拉一条干净的开发分支,再从旧的开发分支中,把 commit 复制到新分支。

命令使用

1
2
3
4
5
6
7
8
# 一次转移多个提交
git cherry-pick commit1 commit2
# 多个连续的commit,也可区间复制:
git cherry-pick commit1^..commit2
# 放弃 cherry-pick (冲突时使用)
gits cherry-pick --abort
# 退出 cherry-pick
git cherry-pick --quit

revert

描述

给定一个或多个现有提交,恢复相关提交引入的更改,并记录一些这些更改的新提交。这就要求你的工作树是干净的(没有来自头部的修改)。
将现有的提交还原,恢复提交的内容,并生成一条还原记录。

应用场景

有一天测试突然跟你说,你开发上线的功能有问题,需要马上撤回,否则会影响到系统使用。这时可能会想到用 reset 回退,可是你看了看分支上最新的提交还有其他同事的代码,用 reset 会把这部分代码也撤回了。由于情况紧急,又想不到好方法,还是任性的使用 reset,然后再让同事把他的代码合一遍(同事听到想打人),于是你的技术形象在同事眼里一落千丈。

命令使用

1
2
3
# revert 普通提交
git revert 21dcd937fe555f58841b17466a99118deb489212

reflog

描述

此命令管理重录中记录的信息。
如果说 reset –soft 是后悔药,那 reflog 就是强力后悔药。它记录了所有的 commit 操作记录,便于错误操作后找回记录。

应用场景

某天你眼花,发现自己在其他人分支提交了代码还推到远程分支,这时因为分支只有你的最新提交,就想着使用 reset –hard,结果紧张不小心记错了 commitHash,reset 过头,把同事的 commit 搞没了。没办法,reset –hard 是强制回退的,找不到 commitHash 了,只能让同事从本地分支再推一次(同事瞬间拳头就硬了,怎么又是你)。于是,你的技术形象又一落千丈。

总结

本文主要分享了5个在开发中实用的 Git 命令和设置短命令的方式。

  • stash:存储临时代码。
  • reset –soft:软回溯,回退 commit 的同时保留修改内容。
  • cherry-pick:复制 commit。
  • revert:撤销 commit 的修改内容。
  • reflog:记录了 commit 的历史操作。

文中列举的应用场景有部分不太恰当,只是想便于同学们理解,最重要的是要理解命令的作用是什么,活学活用才能发挥最大功效。