Comment puis-je rétablir mes modifications dans un sous-module git?

271

J'ai un sous-module git (RestKit) que j'ai ajouté à mon repo.

J'ai accidentellement changé certains fichiers et j'aimerais revenir à la version source. Pour ce faire, j'ai essayé d'exécuter

Mac:app-ios user$ git submodule update RestKit

Mais comme vous pouvez le voir ici, cela n'a pas fonctionné car il s'agit toujours de "contenu modifié":

Mac:app-ios user$ git status
...
#   modified:   RestKit (modified content)

Même

Mac:app-ios user$ git submodule update -f RestKit 

ne rétablit pas les fichiers modifiés localement.
Comment réinitialiser le contenu de ce sous-module?

Eric
la source
Si git reset --hardcela ne fonctionne pas, essayez d'abord de spécifier la branche distante avec git reset --hard origin/<branch_name>.
Jerry K.

Réponses:

209

Accédez au répertoire du sous-module, puis effectuez une git reset --hardpour réinitialiser tous les fichiers modifiés à leur dernier état validé. N'oubliez pas que cela annulera toutes les modifications non validées.

Jamie Penney
la source
6
La mise à jour du sous-module git (même sans le --init) a fonctionné pour moi d'abandonner les "changements" du sous-module alors que je n'avais rien changé. Si vous allez dans le répertoire du sous-module et que l'état git apparaît vide, essayez ceci au lieu de la réinitialisation.
ADN éclectique du
16
git submodule update --inittravaillé pour moi; sans --initcela ne fonctionnait pas du tout.
Per Lundberg
Superbe!! J'ai apporté des modifications au sous-module dans un dépôt de la mienne où je l'ai importé. Et cela l'a ramené à ce qu'il était censé être.
Noitidart
2
reset --hard ne fonctionnait pas pour moi, mon sous-module ne pouvait toujours pas être désactivé à cause des changements locaux.
malhal
33
en plus de @markshiz, git submodule update -f --initpour mon cas.
otiai10
281

Si vous souhaitez le faire pour tous les sous-modules, sans avoir à changer de répertoire, vous pouvez effectuer

git submodule foreach git reset --hard

Vous pouvez également utiliser l'indicateur récursif pour appliquer à tous les sous-modules:

git submodule foreach --recursive git reset --hard

le corbeau
la source
7
cela fonctionne tellement mieux pour l'automatisation que d'essayer de cd dans chaque répertoire de sous-module.
Travis Castillo
4
Notez que vous pouvez également vouloirgit submodule foreach --recursive git clean -x -f -d
yoyo
1
sur ma machine (Windows utilisant Git 2.22.0) J'ai besoin de guillemets simples autour de la deuxième commande git lors de l'utilisation de l'indicateur --recursive ou cela ne fonctionnera pas: git submodule foreach --recursive 'git clean -x -f -d'
aatwo
196

Une méthode plus sûre que toutes les réponses précédentes:

git submodule deinit -f .
git submodule update --init

La première commande «dissocie» complètement tous les sous-modules, la seconde en fait ensuite une nouvelle vérification.
Cela prend plus de temps que les autres méthodes, mais fonctionnera quel que soit l'état de vos sous-modules.

qwertzguy
la source
1
Malheureusement, cela n'a pas fonctionné dans mon cas (avec des fichiers locaux modifiés dans un sous-module git), la commande "update --init" cracheerror: Your local changes to the following files would be overwritten by checkout
rogerdpack
Pour mettre à jour un sous-module spécifique, procédez comme suit: $ git submodule deinit -f - <submodule_path> puis $ git submodule update --init - <
submodule_path
J'ai essayé toutes les méthodes ci-dessus jusqu'à ce que j'arrive à celle-ci. Pour moi, c'est le seul qui a donné à mon git un air "propre" (sans le *dans mon PS1qui git status -unon'a pas pu expliquer).
Guy Rapaport
60

Eh bien pour moi, ayant

git reset --hard

il suffit de réinitialiser le sous-module à l'état dans lequel il a été extrait, pas nécessaire à l'état / commit référencé par le référentiel principal. J'aurai toujours des "contenus modifiés" comme OP l'a dit. Donc, afin de ramener le sous-module au commit correct, je lance:

git submodule update --init

Ensuite, quand je le fais git status, c'est propre sur le sous-module.

somme de contrôle
la source
submodule update --initne semble malheureusement pas annuler les modifications locales dans mon cas: |
rogerdpack
48

faire 4 étapes séquentielles:

git submodule foreach git reset --hard HEAD
git submodule update
git submodule foreach "git checkout master; git pull"
git submodule foreach git clean -f
jiahut
la source
2
Le seul qui m'a aussi aidé.
Victor Sergienko
question, si le sous-module est nouveau, il n'y aura pas de fichier .git dans ce répertoire, correct? sera la bulle de commande git au référentiel parent?
santiago arizti
1
@jiahut Même après avoir fait cela, j'ai toujours "(nouveaux commits") à côté de mon sous-module lorsque je fais le "statut git" du parent?
David Doria
1
@DavidDoria a git submodule updateété ce qui a résolu le problème (new commits)pour moi.
ubershmekel
31

Cela a fonctionné pour moi, y compris récursivement dans les sous-modules (c'est peut-être pourquoi votre -f n'a pas fonctionné, car vous avez changé un sous-module à l'intérieur du sous-module):

git submodule update -f --recursive
Sergiu Todirascu
la source
12

Essayez d'abord cela, comme d'autres l'ont dit:

git submodule update --init

Si cela ne fonctionne pas, accédez au répertoire du sous-module et utilisez la commande suivante pour voir s'il y a des modifications dans le sous-module:

git status

S'il y a des changements dans votre sous-module, supprimez-les. Vérifiez que vous ne voyez aucun changement lorsque vous exécutez "git status".

Ensuite, revenez au référentiel principal et exécutez à nouveau "git submodule update --init".

Jean Libera
la source
9

Depuis Git 2.14 (Q3 2017), vous n'avez pas besoin d'aller dans chaque sous-module pour faire un git reset(comme dans git submodule foreach git reset --hard)

C'est parce que git reset lui-même sait maintenant comment rentrer récursivement dans les sous-modules.

Voir commit 35b96d1 (21 avril 2017) et commit f2d4899 , commit 823bab0 , commit cd279e2 (18 avr 2017) par Stefan Beller ( stefanbeller) .
(Fusionné par Junio ​​C Hamano - gitster- en commit 5f074ca , 29 mai 2017)

intégré / réinitialisé: ajout du commutateur --recurse-submodules

git-reset est encore un autre manipulateur d'arbre de travail, qui devrait être enseigné sur les sous-modules.

Lorsqu'un utilisateur utilise git-reset et demande de rentrer dans les sous-modules, cela réinitialisera les sous-modules au nom d'objet tel qu'enregistré dans le superprojet, en détachant les HEAD.

Attention : la différence entre:

  • git reset --hard --recurse-submodule et
  • git submodule foreach git reset --hard

est que le premier réinitialisera également votre arborescence de travail du référentiel parent principal, car le dernier ne réinitialiserait que l'arborescence de travail des sous-modules.
Utilisez donc avec prudence.

VonC
la source
7

Pour git <= 2.13, ces deux commandes combinées devraient réinitialiser votre repos avec des sous-modules récursifs:

git submodule foreach --recursive git reset --hard
git submodule update --recursive --init
cmcginty
la source
3

Cela fonctionne avec nos bibliothèques exécutant GIT v1.7.1, où nous avons un référentiel de packages DEV et un référentiel de packages LIVE. Les référentiels eux-mêmes ne sont rien d'autre qu'un shell pour regrouper les actifs d'un projet. tous les sous-modules.

Le LIVE n'est jamais mis à jour intentionnellement, cependant des fichiers de cache ou des accidents peuvent se produire, laissant le dépôt sale. Les nouveaux sous-modules ajoutés au DEV doivent également être initialisés dans LIVE.

Référentiel de packages dans DEV

Ici, nous voulons extraire toutes les modifications en amont dont nous ne sommes pas encore au courant, puis nous mettrons à jour notre référentiel de packages.

# Recursively reset to the last HEAD
git submodule foreach --recursive git reset --hard

# Recursively cleanup all files and directories
git submodule foreach --recursive git clean -fd

# Recursively pull the upstream master
git submodule foreach --recursive git pull origin master

# Add / Commit / Push all updates to the package repo
git add .
git commit -m "Updates submodules"
git push   

Référentiel de packages en LIVE

Ici, nous voulons extraire les modifications qui sont validées dans le référentiel DEV, mais pas les modifications en amont inconnues.

# Pull changes
git pull

# Pull status (this is required for the submodule update to work)
git status

# Initialize / Update 
git submodule update --init --recursive
David H.
la source
2

Si vous souhaitez ignorer toutes les modifications dans l'ensemble du référentiel avec les sous-modules, vous pouvez utiliser

git restore . --recurse-submodules

Cela annulera toutes les modifications apportées au référentiel et aux sous-modules.

Nitin Garg
la source
0

ma façon de réinitialiser tous les sous-modules (SANS détacher et garder leur branche "master"):

git submodule foreach 'git checkout master && git reset --hard $ sha1'

alex_1948511
la source