8

私は git リポジトリ (多かれ少なかれプロジェクトの歴史をカバーしています) と別のソース (いくつかのファイルを含む tarball のみ) を持っています。

tarball からのソースはかなり多くの変更が加えられているので、そこからいくつかを組み込みたいと思います。問題は、変更されたソースの実際の分岐点を見つけて、そこで何が起こったのかを最小限に抑える方法です。

だから私が基本的に望んでいるのは、コードが私が持っているソースの tarball に最も似ている git 履歴の場所を見つけることです。そして、私はそれを手動で行いたくありません。

また、変更されたソースにはファイルのサブセットのみが含まれており、いくつかのファイルが複数に分割されていることにも言及する価値があります。ただし、そこにあるコードには、小さな変更といくつかの追加しかないようです。

自分で試してみたい場合は、ソース付きの tarball がここにあり、Git はGitoriousでホストされています。git://gitorious.org/gammu/mainline.git

4

6 に答える 6

4

一般的なケースでは、実際にはすべてのコミットを調べる必要があります。これは、あるコミットに大きな差分があり、次の小さな差分、次に別の大きな差分、中程度の差分があるかどうかを知る方法がないためです...

あなたの最善の策は、おそらく特定のファイルに限定することでしょう。単一のファイルだけを検討する場合、そのファイルのすべてのバージョンを反復処理するのにそれほど時間はかかりません (git rev-list <path>リストを取得するために使用すると、すべてのコミットをテストする必要がなくなります)。ファイルを変更したコミットごとに、差分のサイズを確認し、最小値をすぐに見つけることができます。少数のファイルに対してこれを行います。うまくいけば、彼らは同意するでしょう!

差分を設定する最善の方法は、単純に tarball にコピーして一時的なコミットを作成することです。これにより、ブランチを呼び出しtarballて比較することができます。そうすれば、これを行うことができます:

git rev-list path/to/file | while read hash; do echo -n "$hash "; git diff --numstat tarball $hash path/to/file; done

すべてのコミットと差分サイズの素敵なリストを取得します (最初の 3 列は SHA1、追加された行数、削除された行数になります)。次に、それを にパイプするだけでawk '{print $1,$2+$3}' | sort -n -k 2、コミットとその差分サイズのソートされたリストが得られます!

テストするファイルを少数に限定できない場合は、次のようなものを手動で実装したくなるかもしれませんgit-bisect。最良のケースでは、差分も小さくなり、それから遠く離れたコミットでは差分が大きくなります。(ニュートンの方法と完全なバイナリ/グリッド検索の間のどこかでしょうか?)

編集:ダグラスの回答で提案されている別の可能性は、一部のファイルが一部のコミットのファイルと同一である可能性があると思われる場合は、 を使用してそれらをハッシュしgit-hash-object、履歴内のどのコミットにそのブロブがあるかを確認することです。それを行う方法についてのいくつかの優れた回答を含む質問があります。少数のファイル (できれば頻繁に変更されたファイル) でこれを行うと、対象のコミットをかなり迅速に絞り込むことができる場合があります。

于 2010-06-23T16:27:38.630 に答える
2

優れた解決策ではありませんが、どのリビジョンであるかを推測するには: tar ボール内のファイルの一部が、分岐されてから変更されていないと仮定します。tar ボール内の各ファイルに対してgit ハッシュ オブジェクトを実行し、 git showを使用してリポジトリ内のそれらのファイルを検索します。次に、おそらくgit whatchangedを使用して、これらのファイルが含まれていたコミットを見つけてみてください。あなたの質問に対する答えは、最も一般的なファイルをコミットすることかもしれませんが、それでも少しヒットとミスがあります。

于 2010-06-23T16:21:58.517 に答える
1

araqnid が言ったことに基づいて、私は 9c6c864426bf88429e77c7e22b5aa78e9295b97a を思いつきました (0.61.0 と HEAD の間のものを求めただけです) これはおそらく最善ではありません)

git rev-list --no-merges --all | while read rev; do patchsize=$(git diff $rev | wc -c); echo $patchsize $rev; done | sort -n | less

tarball を git にインポートし、そのリビジョンをチェックアウトしたと仮定します (これは untar してから

git init
git add .
git commit -m "import tarball"
git remote add origin git://gitorious.org/gammu/mainline.git

したがって、それを実行して上記を実行すると、すべての差分のサイズが patchsize の昇順で出力されます (現在のヘッドが見つかるため、最初の差分は 0 になります)。長い時間がかかります...しかし、最小の差分を見つける必要があります...

于 2010-06-23T18:41:49.597 に答える
0

フォークが発生した場所について大まかな考えがある場合は、Will Manley の を使用することを検討してgit meldください。(参照: meld でブランチの違いを表示しますか? .)

これを行うには、tarball の内容をリポジトリに追加します (いずれにせよ、これを行います)。Meld と をインストールしたらgit-meld、実行します。

git meld branch_from_tarball commit_to_check &

違いが最も少ないコミットが見つかるまで、さまざまなコミットで。このコマンドはmeld、ディレクトリ ツリーを開いて、指定したコミット間の変更を表示します。同一のファイルは非表示になります。スクリーンショットの例:

2 つの非常に異なるコミットを示す Meld:
とても違う

2 つの同様のコミットを表示: 似ている

于 2013-01-11T19:18:11.907 に答える
0

tarball 内のファイルを git リビジョン、別のブランチ、または完全に新しいものにインポートします。リビジョン グラフ内の位置は重要ではありません。ツリーとして利用できるようにしたいだけです。

マスターの各リビジョンについて、そのツリー/リビジョン (「インポート済み」) と比較して、差分の大きさを出力するだけです。何かのようなもの:

git rev-list master | while read rev; do patchsize=$(git diff $rev imported | wc -c); echo $rev $patchsize; done

したがって、非常に大まかな経験則により、最小のパッチ サイズを持つリビジョンが「最も近い」ものになります。(同一のリビジョンはパッチ サイズ 0 を生成し、それ以外は確実にゼロ以外になり、変更が多いほど大きくなります)。

于 2010-06-23T16:29:14.100 に答える
0

フォークはどのように作られましたか?誰かが作って自分の仕事をしたクローンですか?もしそうなら、これは本当に簡単です。必要なのは、フォークからコードを取得するローカル ブランチを作成することだけです。git は、元のリポジトリのコミットの 1 つを指しているフォークされたブランチの祖先を確認し、いわば「ドットを接続」します...元のリポジトリの履歴をフォークに再接続します。

あなたはこれを行うことができるはずです:

git remote add thefork git://wherever.it.lives/thefork.git

git fetch thefork

git branch -f thefork-branch thefork/branchname

git checkout thefork-branch

この時点で、分岐したブランチとローカル リポジトリの完全な履歴を実行gitkして表示し、それらが接続されているかどうかを確認できます。

于 2010-06-23T15:54:44.760 に答える