2011-07-18 29 views
13

しかし、私はちょうど、次のようになるのは、私は以下の歴史Gitのログ履歴の簡素化

 D---E-------F 
    / \  \ 
     B---C---G---H---I---J 
    /     \ 
    A-------K---------------L--M 

gitのログ--ancestryパスD..Mは私に

  E-------F 
      \  \ 
       G---H---I---J 
          \ 
          L--M 

を与える持っているとしましょう

  E 
      \  
       G---H---I---J 
          \ 
          L--M 

それとも

  E-------F 
        \ 
         I---J 
          \ 
          L--M 

本質的に、私は2つではなく1つのパスを横切りたいと思います。

これは可能ですか?もしそうなら、コマンドは何ですか?

編集:

私は--first-親を使用して試してみたが、これはまさにそれではありません。 --first-親G..M FがIの最初の親である代わりに、私は

    H---I---J 
          \ 
          L--M 

をたいすべてのヘルプは次のようになりますので、それは、Fが含まれて私に

    F 
        \ 
        H---I---J 
          \ 
          L--M 

を与える gitのログ

ソリューション

を高く評価(それは私のために働いていた):

@VonCが述べたように、これを行い、単一のワンライナーがありません。だから私はbashスクリプトを使い終わった。それぞれについて、

  1. は、$コミットの親が、はい、続行した場合、我々は
  2. に以前あっコミット含まれている場合は「gitのログ--ancestryパスG..M」が
  3. 決定にコミット。何か面白いことをする。
  4. いいえの場合は、そのコミットをスキップします。たとえば、

、--first-コミットG..Mが

H - F - I - J - L - M 

でgitのログは、しかし、Fの親はEである、ないH.だから、私たちは私に

H - I - J - L - M 
を与え、Fを省略

よろしく!

答えて

4

OP Ken Hirakawaを期待得ることができた私は、これは実際に

(あなたが含まれるように、事前に正確なリストを知っている限り/ DAGを歩くの目的を否定され、除外)を直接可能であるとは思いませんリニア歴史によって:

git log --pretty=format:"%h%n" --ancestry-path --reverse $prev_commit..$end_commit 

、それぞれが作る、コミットのために必ずそれはコミット以前の直接の子です。

ここにはscript writtten by Ken Hirakawaがあります。ここで


は、DAGを作成するために私のスクリプトは--ancestry-pathため、GitのログmanページのHistory Simplificationに記載されている:

あなたは最後に、私は同様の歴史を作成するために使用されるbashスクリプトがあります(ルートディレクトリの名前とユーザ名で呼び出す)。

私は定義:

$ git config --global alias.lgg "log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %C(bold blue)<%an>%Creset' --abbrev-commit --date=relative" 

私が手:

$ git lgg 
* d7c4459 - (HEAD, M, fromA) M <VonC> 
* 82b011d - (L) Merge commit 'J' into fromA <VonC> 
|\ 
| * 190265b - (J, master) J <VonC> 
| * ef8e325 - (I) Merge commit 'F' <VonC> 
| |\ 
| | * 4b6d976 - (F, fromB) F <VonC> 
| * | 45a5d4d - (H) H <VonC> 
| * | 834b239 - (G) Merge commit 'E' <VonC> 
| |\ \ 
| | |/ 
| | * f8e9272 - (E) E <VonC> 
| | * 96b5538 - (D) D <VonC> 
| * | 49eff7f - (C) C <VonC> 
| |/ 
| * 02c3ef4 - (B) B <VonC> 
* | c0d9e1e - (K) K <VonC> 
|/ 
* 6530d79 - (A) A <VonC> 

そこから、私は祖先パスが返されないI.をコミット

の両親のいずれかを除外することはできません

$ git lgg --ancestry-path D..M 
* d7c4459 - (HEAD, M, fromA) M <VonC> 
* 82b011d - (L) Merge commit 'J' into fromA <VonC> 
* 190265b - (J, master) J <VonC> 
* ef8e325 - (I) Merge commit 'F' <VonC> 
|\ 
| * 4b6d976 - (F, fromB) F <VonC> 
* | 45a5d4d - (H) H <VonC> 
* | 834b239 - (G) Merge commit 'E' <VonC> 
|/ 
* f8e9272 - (E) E <VonC> 

定期D..MMの祖先ですコミットの集合を計算しますが、Dの祖先のあるものを除外:ログのmanページと一致しています。
Mに至るまでの履歴は、Dには「Mには何がありますか」の意味で、Dから何が起こったのかを知るのに便利です。
この例の結果は、AB(およびD自体はもちろん)を除くすべてのコミットになります。私たちはDにより導入されたバグで汚染されているMにコミットするかを調べるたいと固定が必要な場合

、しかし、我々はCを除くすなわち、実際にDの子孫であるD..Mのサブセットのみを表示したい場合がありますおよびK
これはまさに--ancestry-pathオプションの機能です。


#!/bin/bash 

function makeCommit() { 
    local letter=$1 
    if [[ `git tag -l $letter` == "" ]] ; then 
    echo $letter > $root/$letter 
    git add . 
    git commit -m "${letter}" 
    git tag -m "${letter}" $letter 
    else 
    echo "commit $letter already there" 
    fi 
} 

function makeMerge() { 
    local letter=$1 
    local from=$2 
    if [[ `git tag -l $letter` == "" ]] ; then 
    git merge $from 
    git tag -m "${letter}" $letter 
    else 
    echo "merge $letter already done" 
    fi 
} 

function makeBranch() { 
    local branch=$1 
    local from=$2 
    if [[ "$(git branch|grep $1)" == "" ]] ; then 
    git checkout -b $branch $from 
    else 
    echo "branch $branch already created" 
    git checkout $branch 
    fi 
} 

root=$1 
user=$2 
if [[ ! -e $root/.git ]] ; then 
    git init $root 
fi 
export GIT_WORK_TREE="./$root" 
export GIT_DIR="./$root/.git" 
git config --local user.name $2 

makeCommit "A" 
makeCommit "B" 
makeCommit "C" 
makeBranch "fromB" "B" 
makeCommit "D" 
makeCommit "E" 
makeCommit "F" 
git checkout master 
makeMerge "G" "E" 
makeCommit "H" 
makeMerge "I" "F" 
makeCommit "J" 
makeBranch "fromA" "A" 
makeCommit "K" 
makeMerge "L" "J" 
makeCommit "M" 
+0

私は彼が答えを好きになるだろうとは思いませんが、理解する必要のある基本的なポイントがあります:それは直線的ではないので、線形ログは実際のgitでは動作しません開発。たとえば、ChangeLogファイルを作成しようとするときなど、ブランチに入ったすべての変更を知りたい人にとっては不幸です。 ChangeLogファイルが線形履歴であり、開発ができなかったため、たくさんのマージを含むgitからChangeLogファイルを作成するのは実際にはうまくいきません。 –

+1

@Wes:はい、Gitは* content *のマネージャーです.2つのコミットの間でアクセス可能なコミットのコンテンツがマージの結果である場合、DAGを後ろに回ってログを取得すると、その内容に貢献した歴史。 – VonC

+1

私は全くあなたの両方に同意しますが、私はこれに対して1ライナーを持っていないと思いますが、驚くべきことではありません。 VonCの答えは私の質問に答えるので、私はVonCの回答を受け入れるつもりですが、私が思いついた解決策を含めるように質問を編集しました。どうぞご覧ください –