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?
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
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
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.
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.
git submodule update --recursive
aus dem git repo-verzeichnis funktioniert es am besten für mich.
Dadurch werden alle neuesten einschließlich Submodule angezeigt.
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.
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:
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.git checkout master && git pull
aus. Überprüfen Sie auf Fehler.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.
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.
Folgendes funktionierte für mich unter Windows.
git submodule init
git submodule update
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.
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'
Klon- und Init-Submodul
git clone [email protected]:speedovation/kiwi-resources.git resources
git submodule init
Während der Entwicklung ziehen und aktualisieren Sie das Submodul einfach
git pull --recurse-submodules && git submodule update --recursive
git submodule foreach git pull Origin master
git submodule update --remote --merge
Anmerkung: Die letzten beiden Befehle haben dasselbe Verhalten
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
Siehe http://lists.zerezo.com/git/msg674976.html , das einen --track-Parameter einführt
Git für Windows 2.6.3 :
git submodule update --rebase --remote
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 .
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
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.
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
Bemerkung: nicht zu einfach, aber praktikabel und es hat seine eigenen einzigartigen Profis.
Wenn man nur die HEAD
-Revision eines Repositorys und nur HEAD
s 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
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.
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