2012-10-11 12 views
9

すべて特定のファイルの以前のバージョンをgitリポジトリに取得します。git - 特定のファイル/フォルダの以前のバージョンをすべて取得します。

checkoutコマンドで特定のバージョンを取得することは可能ですが、それらはすべて必要です。また、深さオプションを指定したgit cloneコマンドでは、サブフォルダ(「有効でないリポジトリ名」)を複製できないようです。

可能かどうかは分かりますか?

は、あなたがそれクローンgitの際にファイルの

答えて

9

OPはすべてバージョンを取得したいと考えましたが、回答は届きませんでした。特に、ファイルに何百ものリビジョンがある場合(すべての提案はあまりにも手作業です)。コメントで@Tobiasによって提案された半分の解決策は唯一のものですが、bashループはランダムな順序でファイルを作成し、reposに対して使用されると何百もの空のファイルを生成します。その理由の1つは "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

このスクリプトは機能しますが、いくつかの問題があり、予期しない動作が考えられます。詳細は、[my answer](http://stackoverflow.com/a/43747334/1132502)を参照してください。 –

+0

@Nathan、awesome!あなたがそれを見つけられたらうれしい+1 –

-2

すべてのバージョンが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は何

  • シンボリックリファレンスをすることができ、ファイルの特定のバージョンを取得するにはブランチ、タグ名、リモートも)
  • コミットハッシュ
  • HEAD〜3のような改訂仕様、支社の@ {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. 私はそれをrepoから削除されたファイルに対して実行できるようにしたかったのです。
  4. 私はすべてのブランチですべてのリビジョンを望んでいませんでした。私はHEADからリビジョンに到達できるようにしたかっただけです。
  5. git repoにないとエラーになりました。
  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 
関連する問題