git - 获取特定文件/文件夹的所有先前版本
我想检索全部旧版本的特定文件在git存储库中。git - 获取特定文件/文件夹的所有先前版本
我发现使用checkout命令可以得到一个特定的版本,但我希望它们都可以。而具有depth选项的git clone命令似乎不允许我克隆子文件夹(“无效的存储库名称”)。
你知道这是可能的吗?
谢谢
回答:
OP想要检索所有版本,但答案不会实现。特别是如果该文件有数百个修订(所有建议都过于人工)。唯一的半工作解决方案是由@Tobias在注释中提出的,但是建议bash循环会以随机顺序构建文件,以及在对我们的回购使用时会产生数百个空文件。其中一个原因是“rev-list - all --objects”会列出不同的对象(包括树木 - 但对我们的目的无用)。
我从Tobias的解决方案开始,添加了计数器,清理了一下,最终以下面列出的bash脚本的形式重新发明了轮子。
该脚本将:
- 提取所有文件版本到/ tmp/all_versions_exported
- 以1个参数 - 相对路径git仓库里面的文件
- 给结果档案名称的数字前缀(排序)
- 在结果文件提到检查文件名(从橘子:)
分辨苹果 - 提到在结果文件名提交日期(见下面的输出例子)
- 不创建空的结果文件
猫在/ usr/local/bin目录/ git_export_all_file_versions
用例:
cd /home/myname/my-git-repo git_export_all_file_versions docs/howto/readme.txt
result stored to /tmp/all_versions_exported
ls /tmp/all_versions_exported
0001.17-Oct-2016.ee0a1880ab815fd8f67bc4299780fc0b34f27b30.readme.txt
0002.3-Oct-2016.d305158b94bedabb758ff1bb5e1ad74ed7ccd2c3.readme.txt
0003.29-Sep-2016.7414a3de62529bfdd3cb1dd20ebc1a977793102f.readme.txt
0004.28-Sep-2016.604cc0a34ec689606f7d3b2b5bbced1eece7483d.readme.txt
0005.28-Sep-2016.198043c219c81d776c6d8a20e4f36bd6d8a57825.readme.txt
0006.9-Sep-2016.5aea5191d4b86aec416b031cb84c2b78603a8b0f.readme.txt
<and so on and on . . .>
编辑:如果你看到象这样的错误:
致命的:不是有效的对象名称 3e93eba38b31b8b81905ceaa95eb47bba ed46494:readme.txt
这意味着您已经从git项目的根文件夹启动脚本。
回答:
所有文件的版本已经在git仓库,当你的Git克隆它。您可以创建一个特定的收银台相关联的分支承诺:
git checkout -b branchname {commit#}
这可能足以满足变化的快速和肮脏的人工比较:
- 结帐分支
- 复制到编辑缓冲区
这可能是好的,如果你只有几个版本需要关注,不介意一点手动,尽管git内置命令。
对于脚本解决方案,在其他答案中已经提供了其他一些解决方案。
回答:
git rev-list --all --objects -- path/to/file.txt
列出了与回购路径
相关联的所有斑点获得文件的特定版本
git cat-file -p commitid:path/to/file.txt
(的commitid可以是任何东西
- 象征REF(分支,标签名称;远程)
- a commit hash
- 像HEAD〜3,BRANCH1 @ {4}等进行修订规范
回答:
的文件有时旧版本只能通过git reflog
。最近我遇到了一个情况,那就是我需要挖掘所有提交,即使是在交互式重新绑定期间由于意外覆盖而不再是日志的一部分的提交。
我写了这个Ruby脚本来输出文件的所有以前的版本来找到孤立的提交。 grep这个输出很容易找到我丢失的文件。希望它能帮助别人。
#!/usr/bin/env ruby path_to_file = ""
`git reflog`.split("\n").each do |log|
puts commit = log.split(" ").first
puts `git show #{commit}:#{path_to_file}`
puts
end
同样的事情可以用git log
完成。
回答:
德米特里提供的脚本确实解决了这个问题,但它有一些问题导致我使它适应了我的需要。具体来说:
- 由于我的默认日期格式设置打破了
git show
的使用。 - 我希望按日期顺序排序结果,而不是反向日期顺序。
- 我希望能够针对从回购库中删除的文件运行它。
- 我不希望所有分支上的所有修订;我只是想从HEAD中获得修改。
- 我希望它错误,如果它不是在一个混帐回购。
- 我不想编辑脚本来调整某些选项。
- 它的工作方式效率低下。
- 我不需要输出文件名中的编号。 (适当格式的日期可以达到同样的目的。)
- 我想更安全的“带空格的路径”处理
你可以看到最新的版本我修改in my github repo或这里的精选版本在写这篇文章的:
#!/bin/sh # based on script provided by Dmitry Shevkoplyas at http://stackoverflow.com/questions/12850030/git-getting-all-previous-version-of-a-specific-file-folder
set -e
if ! git rev-parse --show-toplevel >/dev/null 2>&1 ; then
echo "Error: you must run this from within a git working directory" >&2
exit 1
fi
if [ "$#" -lt 1 ] || [ "$#" -gt 2 ]; then
echo "Usage: $0 <relative path to file> [<output directory>]" >&2
exit 2
fi
FILE_PATH="$1"
EXPORT_TO=/tmp/all_versions_exported
if [ -n "$2" ]; then
EXPORT_TO="$2"
fi
FILE_NAME="$(basename "$FILE_PATH")"
if [ ! -d "$EXPORT_TO" ]; then
echo "Creating directory '$EXPORT_TO'"
mkdir -p "$EXPORT_TO"
fi
echo "Writing files to '$EXPORT_TO'"
git log --diff-filter=d --date-order --reverse --format="%ad %H" --date=iso-strict "$FILE_PATH" | grep -v '^commit' | \
while read LINE; do \
COMMIT_DATE=`echo $LINE | cut -d ' ' -f 1`; \
COMMIT_SHA=`echo $LINE | cut -d ' ' -f 2`; \
printf '.' ; \
git cat-file -p "$COMMIT_SHA:$FILE_PATH" > "$EXPORT_TO/$COMMIT_DATE.$COMMIT_SHA.$FILE_NAME" ; \
done
echo
exit 0
输出的例子:
$ git_export_all_file_versions bin/git_export_all_file_versions /tmp/stackoverflow/demo Creating directory '/tmp/stackoverflow/demo'
Writing files to '/tmp/stackoverflow/demo'
...
$ ls -1 /tmp/stackoverflow/demo/
2017-05-02T15:52:52-04:00.c72640ed968885c3cc86812a2e1aabfbc2bc3b2a.git_export_all_file_versions
2017-05-02T16:58:56-04:00.bbbcff388d6f75572089964e3dc8d65a3bdf7817.git_export_all_file_versions
2017-05-02T17:05:50-04:00.67cbdeab97cd62813cec58d8e16d7c386c7dae86.git_export_all_file_versions
以上是 git - 获取特定文件/文件夹的所有先前版本 的全部内容, 来源链接: utcz.com/qa/262906.html