使用Git查看文件旧版本的方法
技术背景
在软件开发过程中,我们经常需要查看文件的旧版本,比如排查问题、恢复误删除的代码等。Git作为一款强大的版本控制系统,提供了多种方式来实现这一需求。
实现步骤
使用git show
命令
1
| git show REVISION:path/to/file
BASH
|
其中,REVISION
可以是Git提交的SHA值、标签名、分支名、相对提交名或任何其他能标识提交的方式。
- 示例:查看4次提交之前的
<repository-root>/src/main.c
文件版本:
1
| git show HEAD~4:src/main.c
BASH
|
在Windows的Git中,即使是相对于当前目录的路径,也需要使用正斜杠。
根据日期查看
1
| git show HEAD@{2013-02-25}:./fileInCurrentDirectory.txt
BASH
|
这里的HEAD@{2013-02-25}
表示在该仓库中2013年2月25日时HEAD
的位置。
1
| git show $(git rev-list -1 --before="2013-02-26" HEAD):./fileInCurrentDirectory.txt
BASH
|
使用gitk
图形界面工具
- 启动
gitk
:
- 在屏幕顶部选择所需的版本,可以根据描述或日期进行选择。默认情况下,屏幕底部显示该版本的差异(对应“patch”单选按钮)。
- 查看所选版本的文件:
- 点击“tree”单选按钮,将显示该版本的文件树的根目录。
- 逐级展开找到所需的文件。
通过commit hash
查看
- 显示指定文件的所有更改日志:
1
| git log /path/to/file
BASH
|
- 在显示的更改列表中,找到
commit hash
,如commit 06c98...
。 - 复制
commit hash
。 - 运行命令:
1
| git show <commitHash>:/path/to/file
BASH
|
注意,指定相对路径时添加./
很重要,例如:
1
| git show b2f8be577166577c59b55e11cfff1404baf63a84:./flight-simulation/src/main/components/nav-horiz.html
BASH
|
其他方法
导出文件
1
| git show HEAD@{2013-02-25}:./fileInCurrentDirectory.txt > old_fileInCurrentDirectory.txt
BASH
|
快速查看文件与旧版本的差异
1 2 3
| git show -1 filename.txt git show -2 filename.txt git show -3 fielname.txt
BASH
|
使用git log -p
查看更改日志和差异
然后按/
,输入文件名并按enter
。按n
或p
查看下一个或上一个匹配项。
方法一
- 使用
git reflog
查找提交ID。 - 列出提交中的文件:
1
| git diff-tree --no-commit-id --name-only -r <commitHash>
BASH
|
例如:
1
| git diff-tree --no-commit-id --name-only -r d2f9ba4
BASH
|
- 打开所需文件:
1
| git show <commitHash>:/path/to/file
BASH
|
例如:
1
| git show d2f9ba4:Src/Ext/MoreSwiftUI/ListCustom.swift
BASH
|
方法二
注意:此方法可能会丢失未提交的数据,请先提交或保存未提交的文件到暂存区。
- 使用
git reflog
查找提交ID。 - 硬重置到该提交:
1
| git reset --hard %commit ID%
BASH
|
例如:
1
| git reset --hard c14809fa
BASH
|
- 进行必要的更改并在所需分支上进行新的提交。
方法三(适用于MacOS,TaoGit)
按照特定截图步骤操作后,即使提交的数据在分离头指针的提交中“丢失”,也可以复制所有需要的数据。
导出文件所有版本的脚本
1
| git_dump_all_versions_of_a_file.sh path/to/somefile.txt
BASH
|
可以从这里获取脚本。
从给定版本获取多个文件的脚本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
|
import argparse import os import subprocess
parser = argparse.ArgumentParser() parser.add_argument('revision') parser.add_argument('files', nargs='+') args = parser.parse_args() toplevel = subprocess.check_output(['git', 'rev-parse', '--show-toplevel']).rstrip().decode() for path in args.files: file_relative = os.path.relpath(os.path.abspath(path), toplevel) base, ext = os.path.splitext(path) new_path = base + '.old' + ext with open(new_path, 'w') as f: subprocess.call(['git', 'show', '{}:./{}'.format(args.revision, path)], stdout=f)
PYTHON
|
使用方法:
1
| git-show-save other-branch file1.c path/to/file2.cpp
BASH
|
在编辑器中打开结果
1 2 3
| REVISION='...' git show "$REVISION":path/to/file | vim -
BASH
|
在Vim中,可以通过显式设置filetype
来解决语法高亮问题:
1
| git show "$REVISION":path/to/file.py | vim -c 'set filetype=python' -
BASH
|
比较两个历史版本的文件
1
| vimdiff <(git show "$REV_0":path/to/file) <(git show "$REV_1":another/path/to/file)
BASH
|
使用GUI方式
1 2
| sudo apt install libcgi-pm-perl gamin git instaweb --httpd=apache2
BASH
|
将apache2
替换为你的Web服务器,或者事先安装lighttpd
。执行这些命令后,浏览器将打开,可以使用树状结构和差异比较来查看文件。
核心代码
以下是一些核心代码示例:
1 2 3 4 5 6 7 8 9 10 11
| git show HEAD~4:src/main.c
git show $(git rev-list -1 --before="2013-02-26" HEAD):./fileInCurrentDirectory.txt
git show HEAD@{2013-02-25}:./fileInCurrentDirectory.txt > old_fileInCurrentDirectory.txt
vimdiff <(git show "$REV_0":path/to/file) <(git show "$REV_1":another/path/to/file)
BASH
|
最佳实践
- 在使用
git reset --hard
之前,务必确保已经备份了未提交的更改,以免数据丢失。 - 使用脚本导出文件的所有版本时,确保脚本的权限正确,并且脚本所在的目录在系统的
PATH
中。 - 在使用图形界面工具时,熟悉工具的操作快捷键可以提高效率。
常见问题
git show
命令不显示内容:可能是REVISION
或文件路径指定错误,检查并确认这些信息是否正确。- 在编辑器中打开
git show
的结果时语法高亮不正常:可以像在Vim中那样,显式设置filetype
来解决。 - 使用
git instaweb
时浏览器无法打开:检查Web服务器是否正常运行,以及防火墙是否允许访问相关端口。