2012-05-24 10 views
13

ich zwei Versionen in meinem Repository Angenommen haben ... jeder ist wie folgt getaggt Ein Commit aktualisiert eine Submodulreferenz, um auf ein neues Submodul-Commit zwischen Tag1 und Tag2 zu zeigen. Ich führe den folgenden Befehl aus, und bekomme das:Fügen Sie Submodul Meldungen mit "git log" zu begehen

# 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 diesem Fall war die einzige Änderung eine Aktualisierung des Submoduls. Wie bekomme ich die Commit des Submoduls mit dem Repository des übergeordneten Repositorys verschachtelt?

In diesem Beispiel wird angenommen, dass das übergeordnete Repository auf das SubTag5-Tag im Submodul verweist. Zwei Commits später im Submodul ist ein SubTag6-Tag. Das Commit, das gezeigt wird, aktualisierte den Submodulzeiger, um auf SubTag6 statt SubTag5 zu zeigen. Was ich möchte, ist git log, zusätzlich zu dem bereits ausgedruckten Commit, drucken Sie auch die beiden Submodul-Commits, die das Submodul von SubTag5 nach SubTag6 brachten.

Antwort

6

Sie können die Submoduländerungen nur anzeigen, wenn Sie git log -p verwenden. Der folgende Befehl zeigt den vollständigen Unterschied der einzelnen Commit- und Submoduländerungen an.

git log -p --submodule=log 

Submodul Commit-Nachrichten werden wie folgt aufgelistet werden:

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

Sortieren funktioneller, aber gibt es eine Möglichkeit, einen viel sauberen Ausgang für die Submodule ähnlich das Haupt-Repository zu erhalten, ohne die vollen diff watet ? Git log gibt zum Beispiel den Autor und das Datum und die Nachricht zum vollständigen Übergeben im Haupt-Repository aus. Es wäre schön, Einträge wie diese für Submodule unter dem Commit im Haupt-Repository zu haben, ohne Patch-Diffs. –

+0

Soweit ich weiß gibt es jetzt einen Weg. Aber Sie können immer noch einige reguläre Ausdrücke auf der Ausgabe ausführen, die all die Dinge wegfiltert, die Sie nicht sehen wollen. – iblue

0

Wenn Sie unter Windows arbeiten, können Sie das Powershell-Skript verwenden:

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

Offensichtlich kann es übersetzt werden Bash für den Einsatz unter Linux. Das allgemeine Prinzip ist folgende:

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

Hier ist ein einfacher Bash-Befehl, der eine ASCII-Diagramm (ähnlich gitk) verpflichten erstellt, die das betreffende Modul verschachtelt verpflichtet, wenn ein Modul in der Superproject geändert wird. Er druckt den vollständigen Patch für jeden Commit aus und verwendet dann grep, um den Patch-Inhalt herauszufiltern, wobei nur die Zusammenfassungszeilen und Submoduländerungen übrig bleiben.

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

Es erzeugt eine Ausgabe wie folgt aus:

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

es wäre toll, dies in gitk zu haben! –

Verwandte Themen