Git Reflog
本页详细讨论了 git reflog 命令。Git 使用一种引用日志机制来跟踪分支尖端的更新。许多 Git 命令都接受参数来指定引用,这是指向提交的指针。常见示例包括:
git checkoutgit resetgit merge <ref>
引用日志会跟踪本地存储库中 Git 引用的更新时间。除了分支尖端引用日志外,还为 Git stash 维护了一个特殊引用日志。引用日志存储在本地存储库 .git 目录下的目录中。git reflog 目录可以在 .git/logs/refs/heads/、.git/logs/Head 还有 .git/logs/refs/stash 上找到,前提是在代码存储库中使用了 git stash。
我们详细讨论了 git reflog(在重写历史记录页面上)。本文档将涵盖:git reflog 的扩展配置选项、git reflog 的常见用例和陷阱、如何使用 git reflog 撤销变更等等。
基本用法
最基本的引用日志用例是调用:
git reflog这本质上是一条捷径,相当于:
git reflog show HEAD这将输出 HEAD 引用日志。您应该看到类似于以下内容的输出:
eff544f HEAD@{0}: commit: migrate existing content
bf871fd HEAD@{1}: commit: Add Git Reflog outline
9a4491f HEAD@{2}: checkout: moving from main to git_reflog
9a4491f HEAD@{3}: checkout: moving from Git_Config to main
39b159a HEAD@{4}: commit: expand on git context
9b3aa71 HEAD@{5}: commit: more color clarification
f34388b HEAD@{6}: commit: expand on color support
9962aed HEAD@{7}: commit: a git editor -> the Git editor访问重写历史记录页面,查看常见引用日志访问的另一个示例。
引用日志引用
默认情况下,git reflog 将输出 HEAD 引用的引用日志。HEAD 是对当前活动分支的符号引用。引用日志也可用于其他引用。访问 git 引用的语法是 name@{qualifier}。除了 HEAD 引用外,还可以引用其他分支、标记、远程存储库和 Git stash。
您可以通过执行以下命令来获得所有引用的完整引用日志:
git reflog show --all要查看特定分支的引用日志,请将该分支名称传递给 git reflog show
Bitbucket 将显示创建新的存储库页面。花一些时间查看对话框中的内容。除存储库类型外,您在此页面上输入的任何内容都可以在以后更改。
git reflog show otherbranch
9a4491f otherbranch@{0}: commit: seperate articles into branch PRs
35aee4a otherbranch{1}: commit (initial): initial commit add git-init and setting-up-a-repo docs执行本示例将显示 otherbranch 分支的引用日志。以下示例假设您之前使用 git stash 命令存储了一些变更。
git reflog stash
0d44de3 stash@{0}: WIP on git_reflog: c492574 flesh out intro这将为 Git stash 输出引用日志。返回的引用指针可以传递给其他 Git 命令:
git diff stash@{0} otherbranch@{0}执行后,此示例代码将显示 Git 差异对比输出,将 stash@{0} 的变更与 otherbranch@{0} 引用进行对比。
定时引用日志
每个引用日志条目都附有时间戳。这些时间戳可用作 Git 引用指针语法的 qualifier 令牌。这允许按时间过滤 Git 引用日志。以下是一些可用时间限定符示例:
1.minute.ago1.hour.ago1.day.ago昨天1.week.ago1.month.ago1.year.ago2011-05-17.09:00:00
时间限定符可以组合使用(例如 1.day.2.hours.ago),此外,还接受复数形式(例如 5.minutes.ago)。
时间限定符引用可以传递给其他 git 命令。
git diff main@{0} main@{1.day.ago}此示例将把当前的主分支与一天前的主分支进行比对。如果您想知道某个时间范围内发生的变更,此示例非常有用。
子命令和配置选项
git reflog 接受少量被视为子命令的添加参数。
显示 -git reflog show
show 默认是隐式传递的。例如,以下命令:
git reflog main@{0}等同于以下命令:
git reflog show main@{0}此外,git reflog show 是 git log -g --abbrev-commit --pretty=oneline 的别名。执行 git reflog show <refid> 命令将显示所传入 <refid> 的相关日志。
过期 -git reflog expire
expire 子命令清除旧的或无法访问的引用日志条目。expire 子命令可能会丢失数据。此子命令通常不由最终用户使用,而是由 git 内部使用。将 -n 或 --dry-run 选项传递给 git reflog expire 将执行“试运行”,这将输出哪些引用日志条目被标记为已修剪,但实际上不会对其进行修剪。
默认情况下,引用日志过期日期设置为 90 天。过期时间可以通过将命令行参数 --expire=time 传递给 git reflog expire 或设置 gc.reflogExpire 的 git 配置名称来指定。
删除 -git reflog delete
delete 子命令不言自明,它将删除传入的引用日志条目。与 expire 一样,delete 有可能丢失数据,最终用户通常不会调用。
恢复丢失的提交
Git 永远不会真正丢失任何东西,即使在执行历史记录重写操作(如重基或提交修改)时也是如此。在下一个示例中,我们假设我们对代码存储库做出了一些新变更。我们的 git log --pretty=oneline 如下所示:
338fbcb41de10f7f2e54095f5649426cb4bf2458 extended content
1e63ceab309da94256db8fb1f35b1678fb74abd4 bunch of content
c49257493a95185997c87e0bc3a9481715270086 flesh out intro
eff544f986d270d7f97c77618314a06f024c7916 migrate existing content
bf871fd762d8ef2e146d7f0226e81a92f91975ad Add Git Reflog outline
35aee4a4404c42128bee8468a9517418ed0eb3dc initial commit add git-init and setting-up-a-repo docs然后,我们提交这些变更并执行以下操作:
#make changes to HEAD
git commit -am "some WIP changes"添加了新提交。现在,日志如下所示:
$ git clone
https://emmap1@bitbucket.org/emmap1/bitbucketstationlocations.git
Cloning into 'bitbucketspacestation'...
fatal: could not read
Password for 'https://emmap1@bitbucket.org': No such file or directory如果出现此错误,请在命令行中输入以下内容:
37656e19d4e4f1a9b419f57850c8f1974f871b07 some WIP changes
338fbcb41de10f7f2e54095f5649426cb4bf2458 extended content
1e63ceab309da94256db8fb1f35b1678fb74abd4 bunch of content
c49257493a95185997c87e0bc3a9481715270086 flesh out intro
eff544f986d270d7f97c77618314a06f024c7916 migrate existing content
bf871fd762d8ef2e146d7f0226e81a92f91975ad Add Git Reflog outline
35aee4a4404c42128bee8468a9517418ed0eb3dc initial commit add git-init and setting-up-a-repo docs此时,我们通过执行以下命令对主分支进行交互式变基
git rebase -i origin/main变基期间,我们使用 s 变基子命令标记提交用于压缩。变基期间,我们将一些提交压缩到最近的“一些 WIP 变更”提交中。
因为我们压缩了提交,所以 git log 输出现在如下所示:
40dhsoi37656e19d4e4f1a9b419f57850ch87dah987698hs some WIP changes
35aee4a4404c42128bee8468a9517418ed0eb3dc initial commit add git-init and setting-up-a-repo docs如果我们现在查看 git log,就会发现似乎已经没有被标记为压缩的提交了。如果我们想对其中一个压缩的提交进行操作,该怎么办?也许要从历史记录中删除它的变更?这就是引用日志的用武之地了。
git reflog
37656e1 HEAD@{0}: rebase -i (finish): returning to refs/heads/git_reflog
37656e1 HEAD@{1}: rebase -i (start): checkout origin/main
37656e1 HEAD@{2}: commit: some WIP changes我们可以看到 rebase 的开始和结束有引用日志条目,在此之前是我们的“一些 WIP 变更”提交。我们可以将引用日志引用传递给 git reset,然后重置为变基之前的提交。
git reset HEAD@{2}执行此重置命令会将 HEAD 移至添加了“一些 WIP 变更”的提交,实质上是恢复其他压缩的提交。
摘要
在本教程中,我们讨论了 git reflog 命令。涵盖的一些关键点包括:
如何查看特定分支的引用日志
如何使用引用日志撤销 git 变基
如何指定和查看基于时间的引用日志条目
我们简要提到 git reflog 可以与其他 git 命令一起使用,例如 git checkout、git reset 和 git merge。在各自的页面上了解更多信息。有关引用和引用日志的更多讨论,请单击此处了解更多信息。