我想檢索全部舊版本的特定文件在git存儲庫中。git - 獲取特定文件/文件夾的所有先前版本
我發現使用checkout命令可以得到一個特定的版本,但我希望它們都可以。而具有depth選項的git clone命令似乎不允許我克隆子文件夾(「無效的存儲庫名稱」)。
你知道這是可能的嗎?
謝謝
我想檢索全部舊版本的特定文件在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)。我現在可以檢索所有版本。 – max152
git rev-list --all --objects -- path/to/file.txt
列出了與回購路徑
相關聯的所有斑點獲得文件的特定版本
git cat-file -p commitid:path/to/file.txt
(的commitid可以是任何東西
的文件有時舊版本只能通過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
的使用。你可以看到最新的版本我修改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
先前提供的接受的答案(@sehe)並不直接執行一次檢索所有版本。正如在評論中提到的,我使用了這兩個命令來構建一個java程序(不是可以上傳的一般解決方案)。你的解決方案更好,因爲它提供了我過去的Java程序的最終結果。 – max152
此腳本有效,但存在一些問題和可能的意外行爲。請參閱[我的回答](http://stackoverflow.com/a/43747334/1132502)以獲取詳細信息和更新的腳本。 –
@Nathan,真棒!很高興你發現它有用+1 –