9

「gitlog」出力から線形順序を作成しようとしましたが、すべての試みが失敗しました。私がする必要があるのは、コミットをそのコミットを含む次のリリースにマップすることです。走れない

git tag --contains <commit>

リポジトリには非常に大量のコミット(300,000以上)が含まれているため、コミットごとに。

まず使ってみました

git log --pretty=format:"%ct%H" | sort --key=1,10 

コミット時間に基づいて線形順序を取得します。ただし、これでは100%正確な結果が得られないようです。これは私の最初の質問につながります:

Q1)コミットがメインリポジトリにプッシュされるとき、gitはコミット時間をどのように保存しますか?各コミットの現在のマシン時間をUTCで保存しますか?

「githelplog」も調べましたが、ドキュメントには、デフォルトでgitlogにコミットが時系列で一覧表示されると記載されています。私のプロジェクトでは、エラーが発生していないかどうかを確認しましたが、私が知る限り、コードは正しく、gitlogで指定された時系列の順序は線形の順序ではありません。最後に、私の質問は?

Q2)gitがリビジョン番号を保存しない場合、「git log」から線形順序を取得するにはどうすればよいですか?

ありがとう :)

4

1 に答える 1

12

#1: コミットがメイン リポジトリにプッシュされると、git はどのようにコミット時間を保存しますか? 各コミットの現在のマシン時刻を UTC で保存しますか?

からman git-commit:

Git 内部フォーマット
[unix タイムスタンプ] [タイムゾーン オフセット] です。[unix タイムスタンプ] は UNIX エポックからの秒数です。[timezone offset] は、UTC からの正または負のオフセットです。

これに基づいて、git 内部で使用される時間形式は、マシンの UTC オフセットを含むUNIX エポック時間です。

#2: git がリビジョン番号を保存しない場合、"git log" から線形順序を取得するにはどうすればよいですか?

使用した方法 ( ) は、現在のブランチにマージされたすべてのブランチgit log --pretty=format:"%ct%H"からデータを取得します。

これにより、「線形順序」がやや難しくなります。以下を検討してください [ソース: git-scm.org ]:

複数のブランチ、事前マージ

そのため、ここではいくつかの「トピック ブランチ」に取り組んでいます。次に、一部 (dumbideaおよびiss91v2) を保持し、残り ( ) を破棄することにしiss91ます。したがって、 and を破棄C5C6、他のコミットを保持します。マージ後の履歴は次のようになります [ソース: git-scm.org ]:

マージ後

(から children の矢印ポイントparents;C14はcommitsおよびのです)。C13C11

これで、単一のHEADコミットが得られました。議論のために、これをRELEASE1何かとしてリリースすると仮定します。では、質問に対して: この履歴を使用して、どのようにコミットの線形で時系列的に正しいリストを抽出できますか?

簡単な答え: 私はあなたができるとは信じていません。

コミットを時間で直線的に並べ替えることができます。

git log --pretty=format:"%ct %H" | sort --key=1,10

これにより、次のリストが表示されます。

C1
C2
... snip ...
C13
C14

ただし、これは実際には線形の履歴ではないことに注意してください。これは、同時に作成されたいくつかのブランチを一緒にマージしたためです。C14(our )の親の線形履歴を抽出することはできませんHEAD。これは、1 つのコミットの子ではなく、2 つのブランチの子であり、線形関係ではないためです。

では、おそらく 1 つの分岐だけの線形履歴を取得できるのではないでしょうか? C14 -> C13 ... C3 -> C1、 例えば?

これもまた、少なくとも非常に困難であり、(可能性が高い) 不可能です。

複数のブランチが結合している場合 (3 方向以上のマージ)、この問題はさらに複雑になります。この質問では、「単一のブランチ」の履歴を抽出できない理由について詳しく説明します。マージコミットの親を見ているときに、どれが「単一のブランチ」で、どれがどれであるかをどのように判断しますか? 「参加」ブランチですか?


とはいえ、たとえば、この小さなリポジトリのログをグラフ形式で調べると、次のようになります: (役に立たなかったいくつかのコミットを切り取りました)


zsh% git log --graph --all --format=format:'%C(blue)%h%C(reset) - %C(green)(%cr)%C(reset)                %C(yellow)%d%C(reset)' --abbrev-commit --date=relative
* 3cf5f06 - (8 weeks ago)  (origin/master, origin/HEAD, master)
* a3a3205 - (4 months ago) 
* c033bf9 - (4 months ago)  (origin/svg)
* ccee435 - (4 months ago) 
*   f08bc1e - (4 months ago) 
|\  
| * 48c4406 - (5 months ago) 
* | 203eeaa - (4 months ago) 
* | 5fb0ea9 - (5 months ago) 
|/  
* 39bccb8 - (5 months ago)

この歴史年代順であることに注意してください。ただし、枝は 1 つに「平らに」されていないため、少しファンキーに見えます。これらの各コミットは、現在のHEAD( masterorigin/master) に含まれています。履歴の両方のフォークがマージされているため、これは明らかです (マージは で行われf08bc1eます)。

#3: 私がする必要があるのは、そのコミットを含む次のリリースにコミットをマップすることです

個々の commitに関心がある場合、この質問、またはリリースにタグが付けられているかどうかが役立ちます。

質問を読むと、各コミットをリリースにマップしたい場合があるようです。それはたいへんな作業であり、私はそれについて多くを助けることはできません - ただし、各コミットをチェックする必要はないと思います。なぜなら、ブランチはマージされ、線形ブランチのヘッドがリリースにある場合は、線形の親もそうです。チェリーピッキングなどを行っていない限り。

時間で並べ替えた場合、最も古いリリースよりも古いすべてのコミットをチェックし、そのコミット ID が最も古いものに含まれている場合は記録し、2 番目に古いものなどに記録し、それを含むリリースが見つかったらリストからコミットを削除します。 、せいぜいnumber of releases*をチェックする必要がありますnumber of commits。最悪の場合、どのリリースにもコミットがありません。最良のケースでは、リリースにはそれ自体よりも古いすべてのコミットが含まれます。これは300,000チェックです。まだたくさんありますが、(私の素朴な心には)実行可能です。

(長い返信で申し訳ありません)。

于 2012-06-26T17:12:04.407 に答える