2011-07-18 100 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 

本質上,我想只遍歷一條路徑,而不是兩條。

這可能嗎?如果是這樣,命令是什麼?

編輯:

我一直在使用--first親試過,但是這不完全是。 git的日誌--first父母G..M給我

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

它包括F,因爲F是一的第一個父相反,我想

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

任何幫助將是讚賞

解決方案(即工作對我來說):

由於@VonC說,有沒有一個班輪做這個。所以我最終使用了一個bash腳本。

  1. 對於每個提交的「git的日誌--ancestry路徑G..M」
  2. 確定是否提交$的母公司包括提交我們以前在
  3. 如果是,繼續。做一些有趣的事。
  4. 如果否,則跳過該提交。

例如,git的日誌--first提交G..M是

H - F - I - J - L - M 

然而,F的母公司是E,不爲H.因此我們省略樓給我

H - I - J - L - M 

耶!

回答

4

我不認爲這是可能的,直接的(除非你事先知道確切的名單包含/排除,這否定了走在DAG的目的)

其實,OP Ken Hirakawa設法得到預期的線性史:

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

而對於每次提交,並確保它是以前的直接子提交。

這裏是script writtten by Ken Hirakawa


這裏是我的腳本來創建git的日誌手冊頁的History Simplification節中提到的DAG,爲--ancestry-path

你會發現在最後,我用來創建一個類似的歷史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> 

從那裏,我不能排除的父母一方犯一

祖先路徑不會返回:

$ 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..M計算的一組是M祖先提交的,但排除是D祖先的人。
這對於查看從D以來導致M的歷史記錄發生了什麼很有用,意思是「MD中不存在什麼」。
在這個例子中的結果將是所有的提交,當然除了AB(和D本身)。

當我們想找出M什麼承諾被污染與D介紹了錯誤和需要修復,但是,我們可能希望只查看實際上的D後裔的D..M子集,即排除CK
這正是--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文件時。從git生成ChangeLog文件並進行大量合併實際上效果不佳,因爲ChangeLog文件是線性歷史記錄,而且開發不是。 –

+1

@Wes:是的,Git是一個* content *管理器,如果內容(來自兩次提交之間可訪問的提交)是合併的結果,如果日誌返回DAG,可以忽略部分if對所述內容作出貢獻的歷史。 – VonC

+1

我完全同意你們兩個,但我想沒有一個單一的線路,這是不值得驚訝的。我將接受VonC的答案,因爲它回答了我的問題,但我編輯了問題以包含我提出的解決方案。請看看 –