专栏首页mwangbloggit版本控制

git版本控制

查看提交历史 git log

如果想要查看git的提交历史,可以使用git log命令。本文会介绍一些常用的命令选项,比如-<n>-p--stat--pretty等。

默认的git log命令会显示所有提交历史:

$ git log
commit ccf42476e007db608813193659a5b4a0d3241df3Author: wm <1626364188g@gmail.com>Date:   Fri Dec 29 11:31:54 2017 +0800

    change .gitignore

commit da2b5d3db249617ec4b79eb843681600ed141cc9Author: wm <1626364188g@gmail.com>Date:   Fri Dec 29 11:07:36 2017 +0800

    add a.txt to .gitignore

commit eb691cca8f9a227d321924ffd094bcfae03d5314Author: wm <1626364188g@gmail.com>Date:   Fri Dec 29 11:05:52 2017 +0800

    rename README.txt -> README.md

commit 7c14f66174395dfc30ced57840ad5e9f108c9a0cAuthor: wm <1626364188g@gmail.com>Date:   Thu Dec 28 23:47:35 2017 +0800

    delete b.txt# 省略

每个提交的格式都相似,单词commit(提交)后面跟的一大串(实际是40个)字符,就是这个提交的名字,是一个SHA-1序列,独一无二。接下来显示作者以及提交日期,最后显示提交的描述。

如果只想查看最近的几次提交记录,可以使用-(n)选项,比如-2选项只会显示最近的两次提交:

$ git log -2commit ccf42476e007db608813193659a5b4a0d3241df3Author: wm <1626364188g@gmail.com>Date:   Fri Dec 29 11:31:54 2017 +0800

    change .gitignore

commit da2b5d3db249617ec4b79eb843681600ed141cc9Author: wm <1626364188g@gmail.com>Date:   Fri Dec 29 11:07:36 2017 +0800

    add a.txt to .gitignore

使用-p选项可以查看每次的更改:

$ git log -p -1commit ccf42476e007db608813193659a5b4a0d3241df3Author: wm <1626364188g@gmail.com>Date:   Fri Dec 29 11:31:54 2017 +0800

    change .gitignore

diff --git a/.gitignore b/.gitignore
index eaa5fa8..e69de29 100644--- a/.gitignore
+++ b/.gitignore
@@ -1 +0,0 @@
-a.txt

使用-stat选项可以查看每次的简略统计信息:

$ git log --stat -1
commit ccf42476e007db608813193659a5b4a0d3241df3
Author: wm <1626364188g@gmail.com>
Date:   Fri Dec 29 11:31:54 2017 +0800

    change .gitignore

 .gitignore | 1 -
 1 file changed, 1 deletion(-)

使用--pretty选项可以让信息以友好的方式显示,比如--pretty=oneline会让每条提交信息在一行显示,此外还有shortfullfuller可以用:

$ git log -3 --pretty=oneline
ccf42476e007db608813193659a5b4a0d3241df3 change .gitignore
da2b5d3db249617ec4b79eb843681600ed141cc9 add a.txt to .gitignore
eb691cca8f9a227d321924ffd094bcfae03d5314 rename README.txt -> README.md

--pretty=format可以自定义输出的内容:

$ git log -3 --pretty=format:"%h - %an, %ar : %s"ccf4247 - wm, 30 hours ago : change .gitignore
da2b5d3 - wm, 31 hours ago : add a.txt to .gitignore
eb691cc - wm, 31 hours ago : rename README.txt -> README.md

上面的例子中哈希值名字是以简短的开头的几个字母来表示的。

--pretty=format常用的选项如下:

选项

说明

%H

提交对象(commit)的完整哈希字串

%h

提交对象的简短哈希字串

%T

树对象(tree)的完整哈希字串

%t

树对象的简短哈希字串

%P

父对象(parent)的完整哈希字串

%p

父对象的简短哈希字串

%an

作者(author)的名字

%ae

作者的电子邮件地址

%ad

作者修订日期(可以用 --date= 选项定制格式)

%ar

作者修订日期,按多久以前的方式显示

%cn

提交者(committer)的名字

%ce

提交者的电子邮件地址

%cd

提交日期

%cr

提交日期,按多久以前的方式显示

%s

提交说明

git log的常用选项如下:

选项

说明

-p

按补丁格式显示每个更新之间的差异

--stat

显示每次更新的文件修改统计信息

--shortstat

只显示 --stat 中最后的行数修改添加移除统计

--name-only

仅在提交信息后显示已修改的文件清单

--name-status

显示新增、修改、删除的文件清单

--abbrev-commit

仅显示 SHA-1 的前几个字符,而非所有的 40 个字符

--relative-date

使用较短的相对时间显示(比如,“2 weeks ago”)

--graph

显示 ASCII 图形表示的分支合并历史

--pretty

使用其他格式显示历史提交信息。可用的选项包括 oneline,short,full,fuller 和 format(后跟指定格式)

除此之外,git log还有很多输出限制选项,比如--since--until就很常用,其中选项--since会显示某个时间点之后的提交历史,而--until会显示某个时间点之前的历史,下面是一个例子:

$ git log --since=2.days --pretty=format:'%h %cr : %s'ccf4247 33 hours ago : change .gitignore
da2b5d3 34 hours ago : add a.txt to .gitignore
eb691cc 34 hours ago : rename README.txt -> README.md7c14f66 2 days ago : delete b.txt389faae 2 days ago : add b.txt
a2e55d5 2 days ago : delete a.txt381fe8e 2 days ago : add a.txt136fc21 2 days ago : git is covenient

上面的例子以--pretty=format指定的格式显示出了两天以内的提交历史。

git log常用的输出限制选项:

选项

说明

-(n)

仅显示最近的 n 条提交

--since, --after

仅显示指定时间之后的提交

--until, --before

仅显示指定时间之前的提交

--author

仅显示指定作者相关的提交

--committer

仅显示指定提交者相关的提交

--grep

仅显示含指定关键字的提交

-S

仅显示添加或移除了某个关键字的提交

取出 git checkout -- FILE

有的时候难免会写了一些错误的内容,如果想要将工作目录中的文件从暂存区或者git仓库恢复出来,需要使用git checkout命令。git checkout命令,顾名思义,取出的意思。这个命令可以将一个分支的内容取出来放到工作目录,也可将本分支暂存区或者git仓库中的内容取出来放到工作目录,因此它可以用来切换分支,也可以用来恢复文件,这里只讲第二个,也就是恢复文件的用法。

现在让我们在README.md中胡乱的加一句:

$ echo "asdfgh" >> README.md 
$ cat README.md 
Hi, Git!
Git is a free and open source distributed version control system.
Git is very easy to learn.
Git is very fast and convenient.
asdfgh
$ git status
On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)    modified:   README.md

no changes added to commit (use "git add" and/or "git commit -a")

显然,现在git提示我们README.md文件有修改,但是我们发现文件只是多了一句毫无意义的话,现在我们想要恢复修改之前的版本,那么就需要使用git checkout -- FILE命令(当然可以直接删除最后一句话,这只是一个人为制造的例子):

$ git checkout -- README.md
$ cat README.md 
Hi, Git!
Git is a free and open source distributed version control system.
Git is very easy to learn.
Git is very fast and convenient.
$ git status
On branch master
nothing to commit, working directory clean

上面的例子中,在checkout后,README.md文件恢复成了在修改之前(上次提交时)的样子,并且工作目录是干净的。

git checkout -- FILE命令按下面的逻辑运行:

  • 如果该文件已经保存到暂存区,那么恢复到暂存区文件的状态。
  • 如果该文件还没有保存到暂存区,那么恢复到上次提交时的状态。

请在执行此命令时务必写上命令中的--

git reset的三个用法与git reflog

git reset,重置。这里讲三个用法,分别是--mixed--soft--hard

  • --mixed:默认命令选项,即不写命令选项时执行此命令选项。仅仅重置暂存区(index)至给定提交,不重置工作目录。
  • --soft:暂存区与工作目录都不会被重置,仅仅把HEAD指向给定提交。执行后效果是自给定提交以来所有的改变都是未提交的。
  • --hard:重置暂存区和工作目录,并且将HEAD指向给定提交。这个命令很危险,因为它会丢失自给定提交以后所有的更改。

下面我们更改README.md,并且将其提交到暂存区:

$ echo "asdfgh" >> README.md
$ git add README.md 
$ git status -s
M  README.md

我们现在README.md被添加了一行无用的内容,并且添加到了暂存区,为了重置暂存区,需要git reset HEAD README.md命令,它使用的是默认的命令选项--mixed,效果是仅仅将暂存区的README.md重置至HEAD(即最近提交),不会重置工作目录:

$ git reset HEAD README.md
Unstaged changes after reset:M   README.md
$ git status -s
 M README.md
$ cat README.md | tail -1
asdfgh

可见,暂存区被重置了,而工作目录并没有被重置。

假设我们没有发现这个问题,这个问题被提交了,有没有补救的方法呢?

$ git commit -a -m "add a wrong line asdfgh to README.md"$ git status -s
$ cat README.md | tail -2
Git is very fast and convenient.
asdfgh
$ git log --pretty=oneline -3
af490893aba74d956c57583078ec0df343a06aae add a wrong line asdfgh to README.md
ccf42476e007db608813193659a5b4a0d3241df3 change .gitignore
da2b5d3db249617ec4b79eb843681600ed141cc9 add a.txt to .gitignore

糟糕,现在已经被提交了,怎么办?这就要用到--hard了,它就将工作目录、暂存区重置,并且将HEAD指向给定提交:

$ git reset --hard HEAD^
HEAD is now at ccf4247 change .gitignore
$ cat README.md | tail -2Git is very easy to learn.
Git is very fast and convenient.
$ git status -s
$ git log --pretty=oneline -2ccf42476e007db608813193659a5b4a0d3241df3 change .gitignore
da2b5d3db249617ec4b79eb843681600ed141cc9 add a.txt to .gitignore

HEAD在重置前指向最新的提交,HEAD^表示最新提交的前一次提交,HEAD^^表示最新提交的前一次提交的前一次提交……为了简便,HEAD~99表示表示最新提交的前99次提交。

所以上例中的git reset --hard HEAD^将工作目录和暂存区全部重置到前一次提交,并且将HEAD指向前一次提交,后面的命令结果显示确实是这样。

git reset --hard ccf4247可以达到同样的效果,它使用给定提交的哈希字符串代替HEAD^,不用把哈希字符串写全,但是最少要保证唯一性,我建议最少写7位。

可见,git reset --hard会将给定提交之后的所有修改丢弃,所以请谨慎使用。

但是现在我们发现最后那句无厘头的话好像还挺有意思,能不能再找回来呢?(你不觉得有意思是正常的,但是书总得往下写)

我们发现git log里的记录已经没有了,怎么办呢?

git reflog记录了所有的索引变化,所以使用该命令可以查到索引变化的日志,便可以从中找到给定提交的哈希字符串了!

$ git reflog
ccf4247 HEAD@{2}: reset: moving to HEAD^
af49089 HEAD@{3}: commit: add a wrong line asdfgh to README.md

从上面看到,添加那行无厘头句子的哈希字符串是af49089...,所以使用git reset --hard af49089就可以啦!

$ git reset --hard af49089
HEAD is now at af49089 add a wrong line asdfgh to README.md
$ cat README.md | tail -2Git is very fast and convenient.
asdfgh
$ git log --pretty=oneline -2af490893aba74d956c57583078ec0df343a06aae add a wrong line asdfgh to README.md
ccf42476e007db608813193659a5b4a0d3241df3 change .gitignore
$ git status -s
$ 

现在都找回来啦哈哈!

最后,来说说--soft选项,它不会重置工作目录与暂存区,只会将HEAD指向给定提交。效果是自给定提交以来所有修改都是未提交状态。

现在我们将再向README.md中添加两句话,并且分别提交:

$ echo "qwerty" >> README.md
$ git commit -a -m "add qwerty to README.md"[master 721f8ff] add qwerty to README.md 1 file changed, 1 insertion(+)
$ echo "zxcvbn" >> README.md
$ git commit -a -m "add zxcvbn to README.md"[master 64e53ee] add zxcvbn to README.md 1 file changed, 1 insertion(+)
$ git status -s
$
$ git log --pretty=oneline -364e53eeb47738ffd81ff7770758b774f60080b46 add zxcvbn to README.md721f8ffb54bd93e7d75aed6ff9bf93e2f9eb8ca1 add qwerty to README.md
af490893aba74d956c57583078ec0df343a06aae add a wrong line asdfgh to README.md

好的,现在我们确定这两个提交都是正确无误的,希望它们能“合并”成一个提交,怎么办?

git reset --soft将帮助我们解决这个问题,它不会修改工作目录和暂存区,只修改HEAD的指向。

$ git reset --soft af49089
$ git status -s
M  README.md
$ cat README.md | tail -2
qwerty
zxcvbn

上面的例子中,新添加的两行都成了未提交的内容。现在提交就可将他们合并成一个提交:

$ git commit -a -m "add two wrong line to README.md"[master 14bd627] add two wrong line to README.md 1 file changed, 2 insertions(+)
$ git log --pretty=oneline -214bd6272cde43128877f191364361a7194ba6e6c add two wrong line to README.md
af490893aba74d956c57583078ec0df343a06aae add a wrong line asdfgh to README.md

本文分享自微信公众号 - mwangblog(mwangblog),作者:WM

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2018-01-03

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • git简介

    mwangblog
  • git,版本控制界的魔术师(1/18/2018)

    mwangblog
  • 免疫算法简单介绍

    mwangblog
  • Git学习01-Learn Git Branching(在线学习工具)

    网址:https://learngitbranching.js.org/?locale=zh_CN

    帅的一麻皮
  • 追求卓越,勇攀高峰 - RWP中国之旅盛大来袭

    编辑手记:3月28日,Oracle RWP 性能之旅,北京站再度来袭!Andrew Holdsworth 和 Graham Wood 将带领大家在一天之内,探...

    数据和云
  • 区块链是未来吗? 或者它只是一种时尚?

    区块链行业和美国大淘金者的共同点 今天用加密货币发生的事情让人联想到90年代的网络泡沫时代。投资科技公司的人们以及更加连接未来的雄心勃勃的想法几乎在一夜之间赚取...

    首席架构师智库
  • 【论文推荐】最新八篇强化学习相关论文—残差网络、QMIX、元学习、动态速率分配、分层强化学习、抽象概况、快速物体检测、SOM

    【导读】专知内容组整理了最近八篇强化学习(Reinforcement learning)相关文章,为大家进行介绍,欢迎查看! 1.BlockDrop: Dyna...

    WZEARW
  • 前端神器之Sublime Text2/3简单明了使用总结

    第一:也是最重要的,它占内存很小(就如同notepad++那般迅速打开,所以那款其实也不错~)。一般IDE比如WebStorm(它也是一款神器来着),Aptan...

    书童小二
  • 区块链可以减少社会不平等吗?

    本文在腾讯云+社区人工智能专栏首发, 为原创翻译文章. 英语原文以引用方式给出 注释部分为译者为文中的相关概念注释 若手机显示不全, 请滑动屏幕 导读 201...

    benny
  • TCB系列学习文章——什么是TCB云开发?(一)

    云开发(Tencent Cloud Base,TCB)是腾讯云为移动开发者提供的高可用、自动弹性扩缩的后端云服务,包含计算、存储、CDN、静态托管等能力(Ser...

    F颜

扫码关注云+社区

领取腾讯云代金券