2012-10-11 63 views
9

我想檢索全部舊版本的特定文件在git存儲庫中。git - 獲取特定文件/文件夾的所有先前版本

我發現使用checkout命令可以得到一個特定的版本,但我希望它們都可以。而具有depth選項的git clone命令似乎不允許我克隆子文件夾(「無效的存儲庫名稱」)。

你知道這是可能的嗎?

謝謝

回答

9

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項目的根文件夾啓動腳本。

+0

先前提供的接受的答案(@sehe)並不直接執行一次檢索所有版本。正如在評論中提到的,我使用了這兩個命令來構建一個java程序(不是可以上傳的一般解決方案)。你的解決方案更好,因爲它提供了我過去的Java程序的最終結果。 – max152

+0

此腳本有效,但存在一些問題和可能的意外行爲。請參閱[我的回答](http://stackoverflow.com/a/43747334/1132502)以獲取詳細信息和更新的腳本。 –

+0

@Nathan,真棒!很高興你發現它有用+1 –

-2

所有文件的版本已經在git倉庫,當你的Git克隆它。您可以創建一個特定的收銀臺相關聯的分支承諾:

git checkout -b branchname {commit#} 

這可能足以滿足變化的快速和骯髒的人工比較:

  • 結帳分支
  • 複製到編輯緩衝區

這可能是好的,如果你只有幾個版本需要關注,不介意一點手動,儘管git內置命令。

對於腳本解決方案,在其他答案中已經提供了其他一些解決方案。

+0

謝謝!我不知道(第一次使用git)。我現在可以檢索所有版本。 – max152

4
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}等進行修訂規範
+0

好的非常感謝!我花了時間去了解(這是我第一次使用git)。我現在可以製作一個腳本來重建所有版本。 – max152

+0

我的廣義答案的具體細節很好的擴展 – gview

+2

@ user1739644你有沒有嘗試轉換存儲庫?看看'git fast-export --all errata.html',它有許多其他VCS-es支持的全文檔,簡單的文件格式。 – sehe

0

的文件有時舊版本只能通過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完成。

4

德米特里提供的腳本確實解決了這個問題,但它有一些問題導致我使它適應了我的需要。具體來說:

  1. 由於我的默認日期格式設置打破了git show的使用。
  2. 我希望按日期順序排序結果,而不是反向日期順序。
  3. 我希望能夠針對從回購庫中刪除的文件運行它。
  4. 我不希望所有分支上的所有修訂;我只是想從HEAD中獲得修改。
  5. 我希望它錯誤,如果它不是在一個混帳回購。
  6. 我不想編輯腳本來調整某些選項。
  7. 它的工作方式效率低下。
  8. 我不需要輸出文件名中的編號。 (適當格式的日期可以達到同樣的目的。)
  9. 我想更安全的「帶空格的路徑」處理

你可以看到最新的版本我修改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 
相關問題