2012-05-24 36 views
13

Supongamos que tengo dos versiones en mi repositorio ... cada uno ha sido etiquetado como sigue:Incluir submódulo los mensajes de confirmación con "git log"

  • Tag1
  • Etiqueta2

Supongamos ahora que una confirmación ha actualizado una referencia de submódulo para apuntar a una nueva confirmación de submódulo entre Tag1 y Tag2. Ejecuto el siguiente comando y obtengo esto:

# 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. 

En este caso, el único cambio fue una actualización del submódulo. ¿Cómo consigo que los commits del submódulo se intercalen con los commits del repositorio padre?

Específicamente, en este ejemplo, suponga que el repositorio principal apunta a la etiqueta SubTag5 en el submódulo. Dos confirmaciones posteriores en el submódulo son una etiqueta SubTag6. La confirmación mostrada actualizó el puntero del submódulo para que apunte a SubTag6 en lugar de SubTag5. Lo que me gustaría hacer es tener git log, además de la confirmación que ya se imprimió, imprimir las dos confirmaciones de submódulo que trajeron el submódulo de SubTag5 a SubTag6.

Respuesta

6

Puede ver los cambios del submódulo, pero solo cuando usa git log -p. El siguiente comando muestra la diferencia completa de cada commit y cambios en el submódulo.

git log -p --submodule=log 

submódulo cometer los mensajes se enumeran así:

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

Algo funcional, pero hay una manera de obtener una salida mucho más limpio para los submódulos similares al repositorio principal, sin vadear a través del diff completo ? Por ejemplo, git log imprime el autor, la fecha y el mensaje de compromiso completo en el repositorio principal. Sería bueno tener entradas como esa para los submódulos enumerados debajo de la confirmación en el repositorio principal, sin parches diffs. –

+0

Por lo que sé, ahora hay camino. Pero aún puede ejecutar algunas expresiones regulares en la salida, lo que filtra todas las cosas que no desea ver. – iblue

0

Si está trabajando en Windows, puede utilizar esta secuencia de comandos 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 "" 
      } 
     } 
    } 
} 

Obviamente se puede traducir golpear para usar en Linux. El principio general es la siguiente:

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

Aquí hay un comando de bash simple que crea un archivo ASCII cometer gráfico (similar a gitk) que intercala el submódulo relevante cuando se comete un submódulo se cambia en el SuperProject. Imprime el parche completo para cada confirmación y luego usa grep para filtrar el contenido del parche, dejando solo las líneas de resumen y los cambios del submódulo.

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

Se produce una salida similar a la siguiente:

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

sería genial tener esto en gitk! –

Cuestiones relacionadas