it-swarm.com.de

Einfachste Möglichkeit, die neuesten Git Module zu ziehen

Wir verwenden git-Submodule, um einige große Projekte zu verwalten, die von vielen anderen von uns entwickelten Bibliotheken abhängig sind. Jede Bibliothek ist ein separates Repo, das als Submodul in das abhängige Projekt eingefügt wird. Während der Entwicklung möchten wir oft die neueste Version jedes abhängigen Moduls verwenden.

Hat git einen eingebauten Befehl, um dies zu tun? Wenn nicht, wie wäre es mit einer Windows-Batchdatei oder einer ähnlichen Datei, die dies tun kann?

1535
Brad Robinson

Bei git 1.8.2 oder höher wurde die Option --remote hinzugefügt, um die Aktualisierung auf die neuesten Tipps von entfernten Zweigstellen zu unterstützen:

git submodule update --recursive --remote

Dies hat den zusätzlichen Vorteil, dass in den .gitmodules- oder .git/config-Dateien angegebene "Nicht-Standard" -Zweige berücksichtigt werden (wenn Sie eine haben, ist die Standardeinstellung Origin/master. In diesem Fall funktionieren einige der anderen Antworten ebenfalls).

Für git 1.7.3 oder höher können Sie verwenden (aber die unten genannten Umschreibungen, welche Updates noch gültig sind):

git submodule update --recursive

oder:

git pull --recurse-submodules

wenn Sie Ihre Submodule auf die neuesten Commits setzen wollen, und zwar auf das, worauf das Repo hinweist.

Hinweis: Wenn dies das erste Mal ist, checken Sie ein Repo aus, müssen Sie zuerst --init verwenden:

git submodule update --init --recursive

Für älter, git 1.6.1 oder höher können Sie etwas Ähnliches (modifiziert nach) verwenden:

git submodule foreach git pull Origin master

Siehe git-submodul (1) für Details

2012

Wenn Sie Material für Submodule in Ihre Submodul-Repositorys ziehen müssen, verwenden Sie dies

git pull --recurse-submodules

ein Feature-Git, der zuerst in 1.7.3 gelernt wurde.

Dies wird jedoch nicht dazu führen, dass in Submodulen die richtigen Commits (auf die Ihr Master-Repository verweist) überprüft werden

Um die korrekten Commits in Ihren Submodulen zu überprüfen, sollten Sie sie nach dem Ziehen mit aktualisieren

git submodule update --recursive --remote
584

Wenn init den folgenden Befehl ausführt:

git submodule update --init --recursive

aus dem git repo-verzeichnis funktioniert es am besten für mich.

Dadurch werden alle neuesten einschließlich Submodule angezeigt.

Erklärt

git - the base command to perform any git command
    submodule - Inspects, updates and manages submodules.
        update - Update the registered submodules to match what the superproject
        expects by cloning missing submodules and updating the working tree of the
        submodules. The "updating" can be done in several ways depending on command
        line options and the value of submodule.<name>.update configuration variable.
            --init without the explicit init step if you do not intend to customize
            any submodule locations.
            --recursive is specified, this command will recurse into the registered
            submodules, and update any nested submodules within.

Danach können Sie einfach ausführen:

git submodule update --recursive

aus dem git repo-verzeichnis funktioniert es am besten für mich.

Dadurch werden alle neuesten einschließlich Submodule angezeigt.

Erklärt

git - the base command to perform any git command
    submodule - Inspects, updates and manages submodules.
        update - Update the registered submodules to match what the superproject
        expects by cloning missing submodules and updating the working tree of the
        submodules. The "updating" can be done in several ways depending on command
        line options and the value of submodule.<name>.update configuration variable.
            any submodule locations.
            --recursive is specified, this command will recurse into the registered
            submodules, and update any nested submodules within.
341
abc123

Hinweis: Dies ist von 2009 und war damals vielleicht gut, aber es gibt jetzt bessere Optionen.

Wir benutzen das. Es heißt git-pup:

#!/bin/bash
# Exists to fully update the git repo that you are sitting in...

git pull && git submodule init && git submodule update && git submodule status

Legen Sie es einfach in ein geeignetes bin-Verzeichnis (/ usr/local/bin). Unter Windows müssen Sie möglicherweise die Syntax ändern, damit sie funktioniert. :)

Update:

In Erwiderung auf den Kommentar des ursprünglichen Autors zum Einzug aller HEADs aller Submodule - das ist eine gute Frage.

Ich bin mir ziemlich sicher, dass git intern keinen Befehl dafür hat. Dazu müssen Sie ermitteln, was HEAD für ein Submodul wirklich ist. Das könnte so einfach sein wie zu sagen, master ist der aktuellste Zweig usw.

Anschließend erstellen Sie ein einfaches Skript, das Folgendes ausführt:

  1. git submodule status auf "geänderte" Repositorys prüfen. Das erste Zeichen der Ausgabezeilen zeigt dies an. Wenn ein Sub-Repo geändert wird, möchten Sie möglicherweise NICHT fortfahren.
  2. cd für jedes aufgelistete Repo in sein Verzeichnis und führen Sie git checkout master && git pull aus. Überprüfen Sie auf Fehler.
  3. Am Ende empfehle ich Ihnen, dem Benutzer eine Anzeige zu drucken, um den aktuellen Status der Submodule anzuzeigen.

Ich möchte erwähnen, dass dieser Stil nicht wirklich das ist, wofür Git-Submodule entwickelt wurden. Normalerweise möchten Sie sagen, dass "LibraryX" auf Version "2.32" ist und so bleibt, bis ich "Upgrade" sage.

Das ist in gewissem Sinne das, was Sie mit dem beschriebenen Skript machen, aber nur automatischer. Vorsicht ist geboten!

Update 2:

Wenn Sie sich auf einer Windows-Plattform befinden, möchten Sie vielleicht mit Python das Skript implementieren, da es in diesen Bereichen sehr gut funktioniert. Wenn Sie unter Unix/Linux sind, empfehle ich Ihnen nur ein Bash-Skript.

Benötigen Sie Klarstellungen? Schreibe einfach einen Kommentar.

301
gahooa

Henrik ist auf dem richtigen Weg. Der Befehl 'foreach' kann ein beliebiges Shell-Skript ausführen. Zwei Optionen, um das Neueste herauszufinden, könnten sein:

git submodule foreach git pull Origin master

und,

git submodule foreach /path/to/some/cool/script.sh

Dadurch werden alle initialized - Submodule durchlaufen und die angegebenen Befehle ausgeführt.

153
mturquette

Folgendes funktionierte für mich unter Windows.

git submodule init
git submodule update
142
zachleat

Bearbeiten :

In den Kommentaren wurde (von philfreo ) darauf hingewiesen, dass die neueste Version erforderlich ist. Wenn es geschachtelte Submodule gibt, die in ihrer neuesten Version enthalten sein müssen:

git submodule foreach --recursive git pull

----- Veralteter Kommentar unten -----

Ist dies nicht der offizielle Weg?

git submodule update --init

Ich benutze es jedes Mal. Bisher keine Probleme.

Bearbeiten:

Ich habe gerade gefunden, dass Sie verwenden können:

git submodule foreach --recursive git submodule update --init 

Dadurch werden auch alle Submodule rekursiv gezogen, d. H. Abhängigkeiten.

33
antitoxic

Da es möglich ist, dass der Standardzweig Ihrer Submodule nicht master ist, automatisiere ich auf diese Weise die vollständigen Upgrades der Git-Submodule:

git submodule init
git submodule update
git submodule foreach 'git fetch Origin; git checkout $(git rev-parse --abbrev-ref HEAD); git reset --hard Origin/$(git rev-parse --abbrev-ref HEAD); git submodule update --recursive; git clean -dfx'
31

Erstes Mal

Klon- und Init-Submodul

git clone [email protected]:speedovation/kiwi-resources.git resources
git submodule init

Sich ausruhen

Während der Entwicklung ziehen und aktualisieren Sie das Submodul einfach

git pull --recurse-submodules  && git submodule update --recursive

Aktualisieren Sie das Git-Submodul mit dem neuesten Commit für Origin

git submodule foreach git pull Origin master

Der bevorzugte Weg sollte unten sein

git submodule update --remote --merge

Anmerkung: Die letzten beiden Befehle haben dasselbe Verhalten

25
Yash

Ich weiß nicht, seit welcher Version von git das funktioniert, aber danach suchst du:

git submodule update --recursive

Ich verwende es zusammen mit git pull, um auch das Root-Repository zu aktualisieren:

git pull && git submodule update --recursive
18
Jens Kohl

Siehe http://lists.zerezo.com/git/msg674976.html , das einen --track-Parameter einführt

6
jerico.dev

Git für Windows 2.6.3 :

git submodule update --rebase --remote

4
seoul

Ich tat dies durch Anpassung von gahooa 's antwort oben :

Integriere es mit einem git [alias] ... 

Wenn Ihr übergeordnetes Projekt in .gitmodules Folgendes enthält:

[submodule "opt/submodules/solarized"]
    path = opt/submodules/solarized
    url = [email protected]:altercation/solarized.git
[submodule "opt/submodules/intellij-colors-solarized"]
    path = opt/submodules/intellij-colors-solarized
    url = [email protected]:jkaving/intellij-colors-solarized.git

Fügen Sie so etwas in Ihrer .gitconfig hinzu

[alias]
    updatesubs = "!sh -c \"git submodule init && git submodule update && git submodule status\" "

Führen Sie dann zum Aktualisieren Ihrer Submodule Folgendes aus:

git updatesubs

Ich habe ein Beispiel davon in meinem Umgebungseinstellungsrepo .

3
Tom

Die obigen Antworten sind gut, aber wir haben git-hooks verwendet, um dies zu vereinfachen. Es stellt sich jedoch heraus, dass Sie in git 2.14git config submodule.recurse auf true setzen können, damit Submodule aktualisiert werden, wenn Sie auf ziehen Ihr Git Repository.

Dies hat den Nebeneffekt, dass alle Submodule geändert werden, wenn sie sich in Zweigen befinden. Wenn Sie dieses Verhalten jedoch bereits benötigen, könnte dies die Aufgabe erfüllen.

Kann gemacht werden mit:

git config submodule.recurse true
3
JamesD

Hier ist die Befehlszeile, die Sie aus allen Git-Repositorys ziehen können, unabhängig davon, ob sie Submodule sind oder nicht:

ROOT=$(git rev-parse --show-toplevel 2> /dev/null)
find "$ROOT" -name .git -type d -execdir git pull -v ';'

Wenn Sie es in Ihrem Top-Git-Repository ausführen, können Sie "$ROOT" durch . ersetzen.

2
kenorb

Von der obersten Ebene im Repo: Git Submodul foreach git checkout Git Submodul foreach git pull

Dadurch werden alle Zweige gewechselt, um sich zu entwickeln und die neuesten Informationen abzurufen

1

Bemerkung: nicht zu einfach, aber praktikabel und es hat seine eigenen einzigartigen Profis.

Wenn man nur die HEAD-Revision eines Repositorys und nur HEADs aller seiner Submodule klonen möchte (d. H. Um "trunk" zu überprüfen), kann das folgende Lua -Skript verwendet werden. Manchmal kann der einfache Befehl git submodule update --init --recursive --remote --no-fetch --depth=1 zu einem nicht behebbaren git-Fehler führen. In diesem Fall müssen Sie das Unterverzeichnis des .git/modules-Verzeichnisses bereinigen und das Submodul manuell mit dem git clone --separate-git-dir-Befehl klonen. Die einzige Schwierigkeit besteht darin, URL, den Pfad des .git-Verzeichnisses des Submoduls und den Pfad des Submoduls im Superprojektbaum herauszufinden.

Anmerkung: Das Skript wird nur gegen https://github.com/boostorg/boost.git-Repository getestet. Seine Besonderheiten: Alle auf demselben Host gehosteten Submodule und .gitmodules enthalten nur relative URL s.

-- mkdir boost ; cd boost ; lua ../git-submodules-clone-HEAD.lua https://github.com/boostorg/boost.git .
local module_url = arg[1] or 'https://github.com/boostorg/boost.git'
local module = arg[2] or module_url:match('.+/([_%d%a]+)%.git')
local branch = arg[3] or 'master'
function execute(command)
    print('# ' .. command)
    return os.execute(command)
end
-- execute('rm -rf ' .. module)
if not execute('git clone --single-branch --branch master --depth=1 ' .. module_url .. ' ' .. module) then
    io.stderr:write('can\'t clone repository from ' .. module_url .. ' to ' .. module .. '\n')
    return 1
end
-- cd $module ; git submodule update --init --recursive --remote --no-fetch --depth=1
execute('mkdir -p ' .. module .. '/.git/modules')
assert(io.input(module .. '/.gitmodules'))
local lines = {}
for line in io.lines() do
    table.insert(lines, line)
end
local submodule
local path
local submodule_url
for _, line in ipairs(lines) do
    local submodule_ = line:match('^%[submodule %"([_%d%a]-)%"%]$')
    if submodule_ then
        submodule = submodule_
        path = nil
        submodule_url = nil
    else
        local path_ = line:match('^%s*path = (.+)$')
        if path_ then
            path = path_
        else
            submodule_url = line:match('^%s*url = (.+)$')
        end
        if submodule and path and submodule_url then
            -- execute('rm -rf ' .. path)
            local git_dir = module .. '/.git/modules/' .. path:match('^.-/(.+)$')
            -- execute('rm -rf ' .. git_dir)
            execute('mkdir -p $(dirname "' .. git_dir .. '")')
            if not execute('git clone --depth=1 --single-branch --branch=' .. branch .. ' --separate-git-dir ' .. git_dir .. ' ' .. module_url .. '/' .. submodule_url .. ' ' .. module .. '/' .. path) then
                io.stderr:write('can\'t clone submodule ' .. submodule .. '\n')
                return 1
            end
            path = nil
            submodule_url = nil
        end
    end
end
1
Orient

Ich denke, dass Sie dazu ein Skript schreiben müssen. Um ehrlich zu sein, installiere ich vielleicht Python, damit Sie os.walk für cd für jedes Verzeichnis verwenden und die entsprechenden Befehle ausgeben können. Die Verwendung von Python oder einer anderen Skriptsprache (außer batch) würde es Ihnen ermöglichen, Teilprojekte auf einfache Weise hinzuzufügen/zu entfernen, ohne das Skript ändern zu müssen.

1
baudtack

Alles was Sie jetzt tun müssen, ist ein einfacher git checkout

Stellen Sie sicher, dass Sie es über diese globale Konfiguration aktivieren: git config --global submodule.recurse true

1
Pellet