当你在工作时, Git 会在后台保存一个引用日志(reflog),引用日志记录了最近几个月你的 HEAD 和分支引用所指向的历史。你可以使用 git reflog 来查看引用日志:
1 2 3 4 5 6 7 8 9 10
MINGW64 /d/coding/git-playground (master) $ git checkout serverfix # 切换分支 Switched to branch 'serverfix' Your branch is up to date with 'origin/serverfix'.
MINGW64 /d/coding/git-playground (serverfix) $ git reflog a1c6f33 (HEAD -> serverfix, origin/serverfix) HEAD@{0}: checkout: moving from master to serverfix # 记录从master切换到serverfix 81d81eb (origin/master, master) HEAD@{1}: checkout: moving from serverfix to master a1c6f33 (HEAD -> serverfix, origin/serverfix) HEAD@{2}: commit: 新增index.html[serverfix]
每当你的 HEAD 所指向的位置发生了变化,Git 就会将这个信息存储到引用日志这个历史记录里。 通过这些数据,你可以很方便地获取之前的提交历史。
你可以使用 @{n} 来引用 reflog 中输出的提交记录, 如果你想查看仓库中 HEAD 在3次前的所指向的提交:
1 2 3 4 5 6 7 8 9 10 11 12 13
$ git show HEAD@{3} commit 81d81eb4595b06d26e7fbeab31fce91816bd8aa4 (origin/master, master) Author: slimterry <slimterry@qq.com> Date: Tue Mar 26 10:14:48 2024 +0800
$ git show HEAD # 查看HEAD所指版本 commit 81d81eb4595b06d26e7fbeab31fce91816bd8aa4 (HEAD -> master, origin/master)
$ git show HEAD^ # 查看HEAD所指的上一个版本 commit 144b12af62f83bbb3e85448371d67afbea999ba8
注意:
命令git show HEAD^等价于git show HEAD^1
git show HEAD^2会直接报错,正确的写法应该是HEAD~2:
1 2 3 4
$ git show HEAD^2 fatal: ambiguous argument 'HEAD^2': unknown revision or path not in the working tree. Use '--' to separate paths from revisions, like this: 'git <command> [<revision>...] -- [<file>...]'
$ git show 81d81eb^ commit 144b12af62f83bbb3e85448371d67afbea999ba8
$ git show 81d81eb^2 fatal: ambiguous argument '81d81eb^2': unknown revision or path not in the working tree. Use '--' to separate paths from revisions, like this: 'git <command> [<revision>...] -- [<file>...]'
MINGW64 /d/coding/git-playground (master) $ git status On branch master Changes to be committed: (use "git restore --staged <file>..." to unstage) modified: C.java
MINGW64 /d/coding/git-playground (hotfix) $ git stash list stash@{0}: WIP on hotfix: b5e0e78 提交D.java stash@{1}: WIP on master: 67e2ce0 c
在本例中,有一个之前做的储藏,所以你接触到了2个不同的储藏工作。
可以通过原来 stash 命令的帮助提示中的命令将你刚刚储藏的工作重新应用:
1 2 3 4 5 6 7 8 9
MINGW64 /d/coding/git-playground (hotfix) $ git stash apply On branch hotfix 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: B.java
no changes added to commit (use "git add" and/or "git commit -a")
$ git stash apply error: Your local changes to the following files would be overwritten by merge: B.java Please commit your changes or stash them before you merge. Aborting On branch hotfix 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: B.java
no changes added to commit (use "git add" and/or "git commit -a")
86182@yawen MINGW64 /d/coding/git-playground (hotfix) $ git stash list stash@{0}: WIP on master: 67e2ce0 c
也可以运行 git stash pop 来应用储藏然后立即从栈上扔掉它:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
MINGW64 /d/coding/git-playground (hotfix) $ git stash list stash@{0}: WIP on master: 67e2ce0 c
MINGW64 /d/coding/git-playground (hotfix) $ git stash pop On branch hotfix 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: C.java
no changes added to commit (use "git add" and/or "git commit -a") Dropped refs/stash@{0} (ac1f4723b275d86c14127b17395be9d2cd759f59)
$ git status -s M B.java # 已暂存 M C.java # 未暂存 $ git stash # 创建储藏 Saved working directory and index state WIP on testchange2: f9ae487 xxx
# 直接应用储藏 $ git stash pop On branch testchange2 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: B.java modified: C.java
no changes added to commit (use "git add" and/or "git commit -a") Dropped refs/stash@{0} (071d62cc3c4bd28dcc7874c035ff272b13385ff1)
$ git stash Saved working directory and index state WIP on testchange2: f9ae487 xxx
$ git stash apply --index On branch testchange2 Changes to be committed: (use "git restore --staged <file>..." to unstage) modified: B.java
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: C.java
$ git st On branch hotfix Changes to be committed: (use "git restore --staged <file>..." to unstage) modified: B.java
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: C.java # 若使用-s命令,显示如下: $ git st -s M B.java # 已暂存 M C.java # 未暂存
此时执行git stash --keep-index:
1 2 3 4 5
$ git stash --keep-index Saved working directory and index state WIP on hotfix: b5e0e78 提交D.java
$ git status On branch hotfix Changes to be committed: (use "git restore --staged <file>..." to unstage) modified: B.java
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: C.java
$ git stash Saved working directory and index state WIP on hotfix: b5e0e78 提交D.java
$ git status On branch hotfix nothing to commit, working tree clean
MINGW64 /d/coding/git-playground (hotfix) $ git stash branch testchanges Switched to a new branch 'testchanges' On branch testchanges 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: B.java modified: C.java
Untracked files: (use "git add <file>..." to include in what will be committed) X.java
no changes added to commit (use "git add" and/or "git commit -a") Dropped refs/stash@{0} (b5efc71b50efa1ddd809903925f9c6b022bb8752)
MINGW64 /d/coding/git-playground (testchanges) # 注意已经自动切换到新分支上 $ git status -s M B.java M C.java ?? X.java
n MINGW64 /d/coding/git-playground (testchanges) $ git stash list
Don’t use the standard ignore rules (see gitignore(5)), but still use the ignore rules given with -e options from the command line. This allows removing all untracked files, including build products. This can be used (possibly in conjunction with git restore or git reset) to create a pristine working directory to test a clean build.
Trace the evolution of the line range given by ,, or by the function name regex , within the . You may not give any pathspec limiters. This is currently limited to a walk starting from a single revision, i.e., you may only give zero or one positive revision arguments, and and (or ) must exist in the starting revision. You can specify this option more than once. Implies --patch. Patch output can be suppressed using --no-patch, but other diff formats (namely --raw, --numstat, --shortstat, --dirstat, --summary, --name-only, --name-status, --check) are not currently implemented.