Cao Yi

第十四章 了解仓库状态

⇦上一章 - 首页🏠 - 下一章⇨



在使用 git 时,我们需要时时刻刻了解 repo 的状态。了解正确的情况,是执行正确操作的前提和保障。

本章部分内容在前面的章节里也有出现。

1. git version

了解当前 git 的版本信息

$ git version
git version 2.40.1

Windows 版本还会带上操作系统信息

$ git version
git version 2.42.0.windows.2

旧版也可以用 git --version

2. git status

git status 请随时使用,随时了解库的状态:

如果仅需简要显示,加参数 -s 即可:git status -s

$ git status
On branch git-tutorial
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
        modified:   git/14.md
        modified:   images/alipay_code.jpg
        modified:   images/wechat_code.png

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

$ git status -s
 M git/14.md
 M images/alipay_code.jpg
 M images/wechat_code.png

git status 非常有用,在各个场景下都应该多用。

3. git diff/difftool

如果工作区里对文件有改动,用 git status 可以知道哪些文件有变化,而用 git diff 可以查看到详细的改动内容。

$ git diff
diff --git a/git/14.md b/git/14.md
index b263c00..18fd84d 100644
--- a/git/14.md
+++ b/git/14.md
@@ -56,7 +56,15 @@ git version 2.42.0.windows.2

 ## `git status`

-`git status` 请随时使用,随时了解库的状态。
+`git status` 请随时使用,随时了解库的状态:
+
...

还可以使用 difftool 查看,效果更酷:

$ git difftool

This message is displayed because 'diff.tool' is not configured.
See 'git difftool --tool-help' or 'git help config' for more details.
'git difftool' will now attempt to use one of the following tools:
opendiff kdiff3 tkdiff xxdiff meld kompare gvimdiff diffuse diffmerge ecmerge p4merge araxis bc codecompare smerge emerge vimdiff nvimdiff

Viewing (1/1): 'git/14.md'
Launch 'vimdiff' [Y/n]?

(这里提到 diff.tool 没有配置,暂时不考虑,它会使用默认的 vimdiff. 配置相关的内容下一章会讲。)

输入 Y 回车后,界面展示如下:

查看上一个版本改动的文件列表:

$ git diff --name-only HEAD~1
git/14.md
images/alipay_code.jpg
images/wechat_code.png

查看前3个版本改动的文件列表:

$ git diff --name-only HEAD~3
git/01.md
git/14.md
git/index.md
git/preface.md
images/alipay_code.jpg
images/wechat_code.png

查看前面版本的具体修改内容:

$ git diff HEAD~1
$ git diff HEAD~3

还可以使用 difftool 查看,效果更酷:

 git difftool HEAD~1
 git difftool HEAD~3

对比某两次 commit 之间修改了哪些文件,如 HEAD~n 到 HEAD~m 的所有变化(包含 HEAD~n 和 HEAD~m)的变化:

$ git diff HEAD~n HEAD~m

如果只是查看变化的文件列表,加 --name-only 参数

$ git diff --name-only HEAD~n HEAD~m

如果需要更好的对比效果,用 difftool

$ git difftool HEAD~n HEAD~m

4. git log

git log 也是一个超级常用的指令,git 作为 VCS, 历史记录是核心,所以这个指令同时也非常重要。

4.1 不带参使用

很多时候,我们执行不带参数指令就好:

$ git log
commit 16018180d2d8033a811561bb044baba9fdf3e4fc (HEAD -> git-tutorial)
Author: Cao Yi <iridiumcao@gmail.com>
Date:   Sat Dec 23 21:21:37 2023 +0800

    more

commit cd5105335c3260daf68af65e9de4173dcb64b54a
Author: Cao Yi <iridiumcao@gmail.com>
Date:   Sat Dec 23 21:08:40 2023 +0800

    Update Chapter 14, 15, 16

commit d61f9eb67ad0dd9818ce6d5028f7676443d699e4
Author: Cao Yi <iridiumcao@gmail.com>
Date:   Sat Dec 23 10:11:06 2023 +0800

    Chapter 15, Git Config
    chapter 16, Git GUI
...

如果记录较多,可以按「方向键」或「翻页键」向前或向后显示,按 q 停止显示并退出。

4.2 瘦身显示

如果不需要显示摘要信息,还可以加上参数 --pretty=oneline 简单显示 commit hash 和 message 就行

$ git log --pretty=oneline
16018180d2d8033a811561bb044baba9fdf3e4fc (HEAD -> git-tutorial) more
cd5105335c3260daf68af65e9de4173dcb64b54a Update Chapter 14, 15, 16
d61f9eb67ad0dd9818ce6d5028f7676443d699e4 Chapter 15, Git Config chapter 16, Git GUI
...

有时我们只需要看最后几行日志,我们可以加上条数限制 -n {num}-{num}

$ git log --pretty=oneline -n 3

$ git log --pretty=oneline -3

--pretty=oneline 会显示每个版本完整的 hash, 很多时候是不需要的,大多数时候只需要简短的 commit hash 即可,这时可用参数 --oneline

$ git log --oneline -3

有时只要列出每次修改的文件名列表就好

$ git log --name-only -3

4.3 图形化显示

--graph 参数可以实现图形化显示,展示分支的衍合历史,如:

$ git log --graph --pretty=oneline --abbrev-commit
*   edd2b51 (HEAD -> hello2) Merge branch 'hello-branch' into hello2
|\
| * 8ac69ff (hello-branch) add executable permission to hello.sh
| * 30fd921 test
| * 2f58933 (origin/hello-branch) file mode
* | e02fdf5 hello52
* | 45e3d20 hello5
|/
* b144824 more

4.4 占位符 (Placeholder)

Git log 支持很多占位符为用户显示定制化的信息。比如:

#   %h: abbreviated commit hash
#   %d: ref names, like the --decorate option of git-log(1)
#   %cn: committer name
#   %ce: committer email
#   %cr: committer date, relative
#   %ci: committer date, ISO 8601-like format
#   %cd: committer date (format respects --date= option)
#   %ct: committer date, UNIX timestamp
#   %an: author name
#   %ae: author email
#   %ar: author date, relative
#   %ai: author date, ISO 8601-like format
#   %s: subject
...

committer date = commit date. committer date 属于一个提交(commit) 的元信息,因为它也表示提交动作发生时的时间,很多时候,用 commit date 也可。

还有很多,建议在官方帮助文档里搜 placeholder 找到相关内容查看。

可以通过 --format--pretty 参数来使用占位符定制消息。

4.4.1 示例1:获取当前分支最后一次提交的作者的 email

有多种方式可以做到:

$ git log -n 1 --format="%ae"
iridiumcao@gmail.com

$ git log -1 --pretty=format:"%ae"
iridiumcao@gmail.com

加上定制信息:

$ git log -1 --format="The last commit's email is %ae"
The last commit's email is iridiumcao@gmail.com
$ git log -1 --pretty=format:"The last commit's email is %ae"
The last commit's email is iridiumcao@gmail.com

如果我们不了解 git log 支持的占位符,就得用下面的笨办法去抓取:

$ git log -n 1 | head -2 | tail -1 | sed 's/^Author: //g'
Cao Yi <iridiumcao@gmail.com>

4.4.2 更多示例

▷ 获取最近19个 commit hash

$ git log -19 --pretty=format:"%h"
$ git log -19 --format=%h

上述两条指令的效果完全一样。

▷ 显示上次修改的文件列表

git show --pretty=%gd --stat
git log -n 1 --stat --summary

上面两条还是有不一样的,show 能看目前未提交的,而 log 只能看已经提交的

Ref

▷ 显示某 branch/tag/commit 的时间信息

当前分支最新 commit 的作者时间(author time):

$ git log -1 --format=%ai
2023-12-23 21:42:03 +0800
$ git log -1 --pretty=%ai
2023-12-23 21:42:03 +0800
$ git log -1 --pretty=format:%ai
2023-12-23 21:42:03 +0800

以上三条指令是等效的。

显示另一个 branch 或 tag 的作者时间:

$ git log -1 --format=%ai master
2023-12-23 07:17:24 +0800

显示某个特定的 commit 的作者时间:

$ git log -1 --format=%ai d61f9eb67a
2023-12-23 10:11:06 +0800

这条指令里的 -1 参数并非多余。

https://stackoverflow.com/questions/3814926/git-commit-date

4.5 Find Deleted Files in Git Repository

假如我们要寻找已经删掉的文件 16.md 在哪些 commit 中处理过,可以这样

$ git log --full-history -- "*16.md"

如果要找最后一条,加参数 -1

$ git log -1 --full-history -- "*16.md"

The quotes are not required, full path can be used too.

Ref: https://stackoverflow.com/questions/6839398/find-when-a-file-was-deleted-in-git/34755406

4.6 查询某人提交的历史记录

可以通过 git message 的 author 包含的字串来找,比如

$ git log --author="Cao Yi"
commit cd5105335c3260daf68af65e9de4173dcb64b54a
Author: Cao Yi <iridiumcao@gmail.com>
Date:   Sat Dec 23 21:08:40 2023 +0800

    Update Chapter 14, 15, 16

commit d61f9eb67ad0dd9818ce6d5028f7676443d699e4
Author: Cao Yi <iridiumcao@gmail.com>
Date:   Sat Dec 23 10:11:06 2023 +0800
...

$ git log --author="iridiumcao"
$ git log --author="iridiumcao@gmail"
$ git log --author="iridiumcao@gmail.com"

查出来的内容还可以进一步格式化或输入到一个文件中

git log --author="Cao Yi" --pretty=oneline >gitlog.txt

5. git reflog

reflog, reference log, 通常认为是 git 日志的日志,凡是对 repository 有改动的操作,它都记录在案,即便是分支删除了,它都在。reflog 只存在于本地,有一段默认的保存时间,可以通过属性 gc.reflogExpire 设置,但不建议用户设置。

$ git config gc.reflogExpire 100.days.ago

它的使用场景主要是恢复一个已经不在版本库中的某个版本。具体处理方法是先用 git reflog 列出记录,再找到那个想要恢复的版本用 git checkout HEAD@{n} -b {new branch name} 恢复。

话说 reflog 的输出真的很难读,不是万不得已,不建议使用。

Ref:

6. git show

不带任何参数时,git show 显示最新版本的摘要信息和具体改动,也就是 git show = git log -1 + git diff HEAD~1.

如果要显示最近 n 个变化,可以用

$ git show HEAD~n

git show 还可以帮助我们获取一些专门信息,比如

获取 committer date (Ref)

git show -s --format=%ci <commit>

示例:

$ git show -s --format=%ci c6664a
2022-01-11 17:17:06 -0500

调节 --format 参数,还可以获取 author date,如

$ git show -s --format=%ai c6664a
2022-01-04 11:49:27 +0800

7. git branch

Branches merged into the master branch

$ git switch master
$ git branch --merged
$ git branch -r --merged
$ git branch -r --merged  | wc -l

Branches NOT merged into the master branch

$ git switch master
$ git branch -r --no-merged

8. git merge-base

git merge-base 是一个比较罕用的指令,可以用它找到两个 branch 分叉的 commit ID. 官方的说明如下:

git-merge-base - Find as good common ancestors as possible for a merge

示例:

$ git merge-base week18 master
645f4089873e48ec7beb1faa1c0518d04d03a1ca

它表示 week18master 这两个分支在 ID 为 645f4089873e48ec7beb1faa1c0518d04d03a1ca 的 commit 分叉。

简明帮助可以通过指令 git merge-base help 查看,详细帮助可以通过这里查看。

9. Tags

10. git worktree

11. git remote

12. git config


⇦上一章 - 首页🏠 - 下一章⇨