2011-07-18 28 views
13

Sadece aşağıdaki istiyorumgit günlüğü geçmişi basitleştirme

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

git log --ancestry yolu D..M Ancak bana

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

verecek en aşağıdaki geçmişi var diyelim

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

Ya

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

Esasen, yalnızca bir yolu değil, yalnızca aşağı doğru ilerlemek istiyorum.

Bu mümkün mü? Ve eğer öyleyse, komut nedir?

Düzenleme:

Ben -Öncelikle-ebeveyn kullanarak denedim ama bu tam olarak öyle değil. F Bunun yerine

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

istiyorum I. birinci üstüdür, çünkü git günlüğü -Öncelikle ebeveynli G..M bana

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

O F içerir

verir Herhangi bir yardım olurdu

Çözüm

takdir (yani benim için çalıştı):

@VonC belirtildiği gibi, bunu yapan bir tek tek satırlık yoktur. Bu yüzden bir bash betiği kullanarak bitti. Her biri için

  1. $ taahhüt ebeveyni evet devam ederse biz
  2. daha önce vardı işlemek içeriyorsa 'git log --ancestry yollu G..M'
  3. belirleyin içinde taahhüt. ilginç bir şey yap.
  4. Hayır ise, bu işlemi atlayın.

Örneğin, git günlüğü G..M Ancak

H - F - I - J - L - M 

olduğunu -Öncelikle-taahhüt, F'nin ebeveyn E değil H. yüzden bana

H - I - J - L - M 
veren F ihmal olduğunu

Yay!

cevap

4

, OP Ken Hirakawabeklenen başardı ben bu Aslında

(dahil etmek önceden kesin liste bilmedikçe/DAG yürüyen amacını ortadan kaldırır, hangi dışlamak) doğrudan mümkün olduğunu düşünmüyorum lineer geçmişi ile:

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

Ve her yapım taahhüt için emin önceki tamamlama doğrudan bir çocuktur.

İşte script writtten by Ken Hirakawa. İşte


git günlüğü adam sayfasının History Simplification bölümünde belirtilen DAG oluşturmak için benim komut dosyası, --ancestry-path içindir:

Sen sonunda ben de benzer bir geçmişi oluşturmak için kullanılan bash komut bulacaksınız (root dir ismini ve kullanıcı adınızı kullanarak).

Ben tanımlayın:

$ 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" 

alıyorum:

$ 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> 

Oradan, ben soy yolu çıkmıyor I.

taahhüt ebeveynleri birini gözardı edilemez:

$ 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üzenli D..MM ataları olan kaydedilmesini kümesini hesaplar, ancak D ataları olanları hariç tutar: log adam sayfası ile tutarlı olan.
Bu, 'dan beri M'a giden tarihe ne olduğunu görmek için yararlıdır, "M, D'da bulunmamış".
Bu örnekte sonuç, A ve B (ve elbette D'un kendisi hariç) tüm taahhütler olacaktır. Biz D tarafından tanıtılan hata ile kirlenmiş olan M yılında taahhüt öğrenmek istiyoruz ve sabitleme gerektiğinde

Ancak biz C hariç yani aslında D torunları D..M yalnızca alt kümesini görüntülemek isteyebilirsiniz ve K.
Bu, tam olarak --ancestry-path seçeneğinin ne yapacağıdır.


#!/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

Onun cevabını olacak sanmıyorum, ama anlaşılması gereken temel bir nokta vardır: doğrusal bir günlük gerçekten git ile çalışmaz bir doğrusal değil çünkü gelişme. Bu, örneğin bir ChangeLog dosyası oluşturmaya çalıştığınızda, örneğin bir dalıma giden tüm değişiklikleri öğrenmek isteyen insanlar için talihsiz bir durumdur. ChangeLog dosyalarını birleştirme ile birleştirmek gerçekten çok işe yaramıyor, çünkü bir ChangeLog dosyası doğrusal bir tarih ve gelişme değildi. –

+1

@Wes: evet, Git bir * içerik * yöneticisidir ve içerik (iki işlem arasında erişilebilir olan işlemlerden) bir birleştirme sonucuysa, bir günlük, geri DAG'yi geri alırsa bölümün görmezden gelmesi sürpriz olabilir. Söz konusu içeriğe katkıda bulunan tarih. – VonC

+1

İkinize de katılıyorum, ama sanırım bunun için bir tek liner olmadığından şaşıracak bir şey yok. VonC'nin cevabını kabul edeceğim çünkü sorumu cevaplıyor, ama soruyu, ortaya koyduğum çözümü dahil etmek için düzenledim. Lütfen –

İlgili konular