2012-05-24 17 views
13

Supponiamo che io ho due versioni nel mio repository ... ciascuno è stato etichettato come segue:Includere modulo commettere messaggi con "git log"

  • Tag1
  • Tag2

Supponiamo ora che un commit ha aggiornato un riferimento al sottomodulo per puntare a un nuovo commit del sottomodulo tra Tag1 e Tag2. Eseguo il seguente comando e ottengo questo:

# show commits between these two tags 
git log Tag1..Tag2 


commit be3d0357b93322f472e8f03285cb3e1e0592eabd 
Author: James Johnston <snip> 
Date: Wed Jan 25 19:42:56 2012 +0000 

    Updated submodule references. 

In questo caso, l'unica modifica era un aggiornamento del sottomodulo. Come si ottiene il commit del sottomodulo da intercalare con il repository principale commesso?

In particolare, in questo esempio, si supponga che il repository principale punti al tag SubTag5 nel sottomodulo. Due commit successivi nel sottomodulo è un tag SubTag6. Il commit mostrato ha aggiornato il puntatore del sottomodulo in modo che punti a SubTag6 invece di SubTag5. Quello che mi piacerebbe fare è avere git log, oltre al commit già stampato, stampare anche i due commit del sottomodulo che hanno portato il sottomodulo da SubTag5 a SubTag6.

risposta

6

È possibile visualizzare le modifiche del modulo, ma solo quando si utilizza git log -p. Il seguente comando mostra la differenza completa di ciascuna modifica di commit e di sottomodulo.

git log -p --submodule=log 

sottomodulo commettere messaggi saranno elencati in questo modo:

Submodule <submodule-name> <starting-commit>..<ending-commit>: 
> Commit message 1 
> Commit message 2 
... 
> Commit message n 
+1

ordine di funzionale, ma c'è un modo per ottenere un'uscita molto più pulito per i moduli simili al repository principale senza guadare attraverso il pieno diff ? Ad esempio, git log stampa l'autore e la data e il messaggio di commit completo sul repository principale. Sarebbe bello avere voci del genere per i sottomoduli elencati sotto il commit nel repository principale, senza differenze di patch. –

+0

Per quanto ne so ora c'è modo. Ma puoi comunque eseguire alcune espressioni regolari sull'output, che filtra via tutto ciò che non vuoi vedere. – iblue

0

Se si sta lavorando su Windows, è possibile utilizzare questo script PowerShell:

function Parse-SubmoduleDiff($rawDiffLines) { 
    $prefix = "Subproject commit " 
    $oldCommitLine = $($rawDiffLines | where { $_.StartsWith("-" + $prefix) } | select -First 1) 
    $newCommitLine = $($rawDiffLines | where { $_.StartsWith("+" + $prefix) } | select -First 1) 

    if ($newCommitLine -eq $null) { 
     return $null 
    } 

    $oldCommit = $null 
    if ($oldCommitLine -ne $null) { 
     $oldCommit = $oldCommitLine.Substring($prefix.Length + 1) 
    } 
    $newCommit = $newCommitLine.Substring($prefix.Length + 1) 
    return @{ OldCommit = $oldCommit; NewCommit = $newCommit } 
} 

# Get the paths of all submodules 
$submodulePaths = $(git submodule foreach --quiet 'echo $path') 
if ($submodulePaths -eq $null) { 
    $submodulePaths = @() 
} 

# Get the log of the parent repository (only SHA1) 
$log = $(git log --format="%H %P" $args) 
foreach ($line in $log) { 

    $parts = $line.Split() 
    $commit = $parts[0] 
    $parents = $parts[1..$parts.Length] 

    # Print the summary for this commit 
    git show --format=medium --no-patch $commit 
    echo "" 

    # Can be more than one parent if it's a merge 
    foreach ($parent in $parents) { 
     # List the paths that changed in this commit 
     $changes = $(git diff --name-only $parent $commit) 

     if ([System.String]::IsNullOrWhiteSpace($parent)) { 
      continue; 
     } 

     foreach ($path in $changes) { 

      if ($submodulePaths.Contains($path)) { 
       # if it's a submodule, the diff should look like this: 
       # -Subproject commit 1486adc5c0c37ad3fa2f2e373e125f4000e4235f 
       # +Subproject commit a208e767afd0a51c961654d3693893bbb4605902 
       # from that we can extract the old and new submodule reference 

       $subDiff = $(git diff $parent $commit -- $path) 
       $parsed = Parse-SubmoduleDiff($subDiff) 
       if ($parsed -eq $null) { 
        continue; 
       } 

       # Now get the log between the old and new submodule commit 
       $oldCommit = $parsed.OldCommit 
       $newCommit = $parsed.NewCommit 
       echo "Submodule '$path'" 
       if ($oldCommit -ne $null) { 
        $range = $($oldCommit + ".." + $newCommit) 
       } else { 
        $range = $newCommit 
       } 

       git --git-dir $path/.git log $range | foreach { " | " + $_ } 
       echo "" 
      } 
     } 
    } 
} 

Ovviamente può essere tradotto bash per l'uso su Linux. Il principio generale è questo:

for each commit in the parent repo 
    print the commit summary 
    for each submodule that has changed in this commit 
     get the old and new commit hashes of the submodule 
     print the log of the submodule between those commits 
    end for 
end for 
9

Ecco un comando bash semplice che crea un ASCII commettere grafico (simile a gitk) che intercala il modulo relativo commette quando un modulo viene modificata nella SuperProject. Stampa la patch completa per ogni commit e poi usa grep per filtrare il contenuto della patch, lasciando solo le righe di riepilogo e le modifiche al sottomodulo.

git log --graph --oneline -U0 --submodule Tag1..Tag2 | grep -E '^[*| /\\]+([0-9a-f]{7} |Submodule |> |$)' 

Produce output simile a questo:

* 854407e Update submodule 
| Submodule SUB 8ebf7c8..521fc49: 
| > Commit C 
* 99df57c Commit B 
* 79e4075 Commit A 
+0

sarebbe fantastico avere questo in gitk! –