赞
踩
这篇文章介绍五个 Git 命令:
git commit --amend
git add -p
git stash
git rebase -i
git reflog
这五个命令不是基础的 Git 命令,它们可能并不广为人知,但非常好用。它们是我在实际工作使用中,排除那些众所周知的、必需的 Git 基础命令之后,根据实用程度所总结出的最想给大家介绍的几个命令。相信其中至少有一个会对你有帮助。
提交 commit 后,稍作检查,发现刚才的 commit 注释写得有问题,如何修改?
啰嗦的办法是,把这个 commit reset 掉,重新提交一个。
但是有更直接好用的方法:
git commit -m <新注释> --amend
git commit
加上 --amend
参数,并用 -m
指明新的注释,执行后便会覆盖掉老的注释。
类似地,如果在提交 commit 后,发现刚才的内容改动还不到位,还需要继续修改文件,如何将新的改动追加到刚才的 commit 中?
可以使用:
git commit --amend <文件/路径>
这会将新的文件变更直接并入刚才提交的 commit 中,同时略过 git add
过程。这里的 <文件/路径>
可以指定多个,用法类似 git add
。
注意:使用 git commit --amend 实际会删除之前的 commit 然后创建新的 commit,通过观察 commit hash 便知。所以,如果你已经将 commit push 至远程仓库,不要使用 git commit --amend(这种情况和 git reset 类似,会导致与远程仓库的 commit 相冲突)。
git add <文件/路径>
会将工作区内的变更移入暂存区,其粒度是文件,也就是说至少针对文件这个级别进行操作,不可以再细分。
如果只想 add 某个文件中的一部分变更内容,而其它部分继续留在工作区,可以使用:
git add -p <文件/路径>
执行该命令后将进入交互模式,Git 将逐一展示文件中各部分的变更,以及询问你如何对其进行处理,你可以自行决定是否将某部分变更放入暂存区。
有时,我们需要临时性地将工作区和暂存区中的全部变更存放到某处,让这两个区域保持干净,以便执行其它操作。
可以使用命令:
git stash
这时工作区和暂存区将变得空空如也,其中的变更被寄存了起来。
当我们想将刚才 stash 的变更恢复回工作区时,可以使用与之搭配的命令:
git stash pop
它可将最近一次 stash 的变更恢复回来。
git stash
背后是一个类似于栈的结构,每次执行 git stash
会将变更放入这个栈的顶部,而 git stash pop
会将最近一次的变更从栈的顶部取出。使用 git stash list
可以查看这个栈中的内容。
git rebase -i
是交互模式下的git rebase
,如果你不了解 git rebase 也没关系,下文避免提及 rebase 相关概念。
git rebase -i
是一个强大的工具,它可以对 commit 序列执行多种操作,包括合并 commit、删除 commit、修改某个 commit 的注释、对 commit 重新排序等。
使用方法:
git rebase -i <commit>
执行上述命令后,将进入 vi 交互模式,可在其中操作该 <commit>
之后所提交的所有 commit。
举个例子,这里有几个 commit:
我想把其中的 7ef54be
(Add python.py) 与 1bdf8a0
(Add java.java) 合并。那么可以这样操作:
git rebase -i cde700c
其中 cde700c
(Add shell.sh)是 1bdf8a0
(Add java.java)的前一个 commit。执行后进入 vi 交互模式中,展示如下内容:
在这个界面里,前几行罗列了参数cde700c
之后所有的 commit,越新提交的 commit 越靠下。每行的格式为:
<命令> <commit_hash> <commit注释>#
开头的行是注释,这些注释简要介绍了所支持的命令。例如默认命令 p (等价于 pick),表示保留这个 commit 且不对它做任何修改。本文只介绍其中的s
、f
和d
命令,其它命令请参考上图注释。
要合并 commit 7ef54be
(Add python.py) 和 1bdf8a0
(Add java.java),可以使用对 7ef54be
(Add python.py)使用 s(或 squash)
命令,如下:
- pick 1bdf8a0 Add java.java
- s 7ef54be Add python.py
- pick 4363536 Add c++.cpp
- pick b44dc74 Add ruby.rb
被标记 s
的 commit 会被并入它的上一个 commit(即 1bdf8a0
(Add java.java))。输入 :wq
保存。之后还将自动进入注释编辑界面,在这里可以编辑合并之后的 commit 的注释。
最终 commit 合并后效果如下:
f(等价于 fixup)
命令与 s
类似,也是执行合并操作。二者区别在与使用 f 后不会进入注释编辑界面,而是直接使用前一个 commit 的注释作为最终注释。
如果要删除 commit 781e313
(Add c++.cpp),使用 d
命令:
- pick cbff37d Add java.java
- d 781e313 Add c++.cpp
- pick b0124ff Add ruby.rb
使用 git reflog
可以浏览本地仓库的所有写操作的历史,写操作包括 commit、pull,reset、merge、rebase、checkout、revert 等。也是说,凡是能改变仓库状态的操作都可以在 reflog 中看到。
如下图是之前介绍 git rebase -i
命令时,执行一系列操作后形成的 reflog:
可以看到这其中有几次 commit 操作,以及几次因执行 git rebase -i
而被记录的 rebase 操作。
读到这里你可能觉得 reflog 不值一提,查到了历史的操作又能怎样呢?其实大有用处,因为一旦知道了执行某个操作时的 commit hash ,就可以通过它将仓库恢复回当时的那个状态。这也许就能挽回你因为误操作而丢掉的代码。
举个例子,之前介绍 git rebase -i
时,我执行了一系列操作,最终仓库变成了这样:
我们想恢复到执行 git rebase -i
之前的状态,该怎么做?
先通过查看 reflog,我们可以找到执行 git rebase -i
之前仓库所处的 commit, 即 b44dc74
(Add ruby.rb),执行:
git reset b44dc74 --hard
一切便恢复如初:
与上面的例子相比,更为常见的情形是,使用 git reset
不小心弄丢了 commit。当然这也可以通过 reflog 找回来。
(全文完)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。