Як повернути свої зміни до підмодулю git?


268

У мене є підмодуль git (RestKit), який я додав до свого репо.

Я випадково змінив деякі файли там і хотів би повернутися до вихідної версії. Для цього я намагався бігати

Mac:app-ios user$ git submodule update RestKit

Але як ви бачите тут, це не спрацювало, оскільки це все ще "модифікований контент":

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

Навіть

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

не повертає локально змінені файли.
Як скинути вміст цього підмодуля?


Якщо git reset --hardце не працює, спершу спробуйте вказати віддалену гілку git reset --hard origin/<branch_name>.
Джеррі К.

Відповіді:


208

Перейдіть до каталогу підмодуля, після чого виконайте git reset --hardскидання всіх змінених файлів до їх останнього скоєного стану. Майте на увазі, що це відкине всі незавершені зміни.


6
оновлення підмодуля git (навіть без --init) працювало на мене, щоб відмовитися від «зміни» підмодуля, коли я насправді нічого не змінив. Якщо ви переходите до каталогу підмодулів, і стан git з’являється порожнім, спробуйте це замість скидання.
Еклектична ДНК

16
git submodule update --initпрацював на мене; без --initцього взагалі не вийшло.
Пер Лундберг,

Чудово !! Я вніс зміни в підмодуль в репо міну, куди імпортував його. І це повернуло її назад до того, що мало бути.
Noitidart

2
скинути - твердий не працював для мене, мій підмодуль все ще не міг бути денінізований через локальні зміни.
мальхал

33
крім @markshiz, git submodule update -f --initдля мого випадку.
otiai10

279

Якщо ви хочете зробити це для всіх підмодулів, не змінюючи каталоги, ви можете виконати

git submodule foreach git reset --hard

Ви також можете використовувати рекурсивний прапор, щоб застосувати до всіх підмодулів:

git submodule foreach --recursive git reset --hard


7
це працює набагато краще для автоматизації, ніж намагання CD у кожен каталог підмодулів.
Травіс Кастільо

4
Зауважте, що ви можете також захотітиgit submodule foreach --recursive git clean -x -f -d
йойо

1
на моїй машині (Windows, що використовує Git 2.22.0) мені потрібні одиничні лапки навколо другої команди git, коли використовується прапор --recursive або він не працюватиме: git submodule foreach --recursive 'git clean -x -f -d'
aatwo

196

Більш безпечний метод, ніж усі попередні відповіді:

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

Перша команда повністю "відв'язує" всі підмодулі, друга потім робить свіжу перевірку їх.
Це займає більше часу, ніж інші методи, але буде працювати незалежно від стану ваших підмодулів.


1
На жаль, це не спрацювало в моєму випадку (із зміненими локальними файлами в підмодулі git), команда "update --init" spewserror: Your local changes to the following files would be overwritten by checkout
rogerdpack

Для оновлення конкретного підмодулю виконайте: $ git submodule deinit -f - <submodule_path>, а потім $ git update submodule --init - <submodule_path>
Priyank

Я спробував усі методи вище, поки не дійшов до цього. Для мене це єдине, що моє git виглядає «чистим» (без того, що було *в моєму, PS1що git status -unoне вдалося пояснити).
Хлопець Рапапорт

60

Ну для мене, маючи

git reset --hard

просто скиньте підмодуль у стан, у якому він перевірився, а не обов'язковий до основного репортажу коміти / стану. Я все ще матиму "модифікований вміст", як сказав ОП. Отже, щоб повернути підмодуль до виправлення, я запускаю:

git submodule update --init

Тоді, коли я це роблю git status, на підмодулі це чисто.


на жаль submodule update --init, не здається, що в моєму випадку все-таки повернути локальні зміни: |
rogerdpack

48

зробити 4 кроки послідовно:

git submodule foreach git reset --hard HEAD
git submodule update
git submodule foreach "git checkout master; git pull"
git submodule foreach git clean -f

2
Єдиний, який мені також допоміг.
Віктор Сергієнко

питання, якщо підмодуль новий, у ньому не буде файлу .git, правильно? чи буде міхур команди git до батьківського репо?
santiago arizti

1
@jiahut Навіть після цього у мене все ще є "(нові коміти") поруч зі своїм підмодулем, коли я роблю "батьківський статус" від батьків?
Девід Дорія

1
@DavidDoria git submodule updateте, що вирішило (new commits)для мене.
ubershmekel

31

Це працювало для мене, включаючи рекурсивно в субмодулі (можливо, тому ваш -f не працював, тому що ви змінили підмодуль всередині підмодуля):

git submodule update -f --recursive

11

Спершу спробуйте це, як казали інші:

git submodule update --init

Якщо це не працює, перейдіть до каталогу підмодулів і скористайтеся наступною командою, щоб побачити, чи є зміни в підмодулі:

git status

Якщо у вашому підмодулі є зміни, позбудьтеся їх. Переконайтеся, що ви не бачите жодних змін під час запуску "статусу git".

Далі, поверніться до основного сховища та знову запустіть "оновлення підмодуля git --init".


9

Оскільки Git 2.14 (Q3 2017), вам не потрібно входити в кожен підмодуль, щоб зробити git reset(як у git submodule foreach git reset --hard)

Це тому, що сам git reset знає, як рекурсивно перейти в підмодулі.

Див. Комісію 35b96d1 (21 квітня 2017 р.) Та виконувати f2d4899 , здійснити 823bab0 , здійснити cd279e2 (18 квітня 2017 р.) Від Стефана Беллера ( stefanbeller) .
(Об’єднав Хуніо С Хамано - gitster- у комітеті 5f074ca , 29 травня 2017 р.)

вбудований / скинутий: додати --recurse-підмодулі комутатор

git-reset це ще один робочий маніпулятор дерев, якого слід навчити про підмодулі.

Коли користувач використовує git-reset і вимагає повторного введення в підмодулі, це скидає підмодулі до імені об'єкта, як записано в надпроекті, від'єднуючи HEAD.

Попередження : різниця між:

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

полягає в тому, що перший також скидає ваше основне батьківське репо-робоче дерево, оскільки останнє скидає лише робоче дерево підмодулів.
Тому використовуйте обережно.


7

Для git <= 2,13 ці дві команди в поєднанні повинні скинути репост із рекурсивними підмодулями:

git submodule foreach --recursive git reset --hard
git submodule update --recursive --init

3

Це працює з нашими бібліотеками, на яких працює GIT v1.7.1, де у нас є репо пакет DEV та репо пакет LIVE. Самі сховища - це не що інше, як оболонка для пакування активів для проекту. всі підмодулі.

LIVE ніколи не оновлюється навмисно, проте файли кешу або аварії можуть статися, залишаючи РЕПО брудним. Нові підмодулі, додані до DEV, також повинні бути ініціалізовані в межах LIVE.

Репозиторій пакетів у DEV

Тут ми хочемо здійснити всі зміни, які ще не знаємо, тоді ми оновимо наше сховище пакетів.

# 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   

Репозиторій пакетів у прямому ефірі

Тут ми хочемо витягнути зміни, які вносяться до сховища DEV, але невідомі зміни вгору.

# Pull changes
git pull

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

# Initialize / Update 
git submodule update --init --recursive

2

Якщо ви хочете відмовитись від усіх змін у всьому сховищі разом із підмодулями, ви можете використовувати

git restore . --recurse-submodules

Це скасує всі зміни, внесені в сховище та в підмодулі.


0

мій спосіб скинути всі підмодулі (БЕЗ відмежування та збереження їх "головного" відділення):

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.