Как мне вернуть мои изменения в подмодуль git?

271

У меня есть подмодуль 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>.
Джерри К.

Ответы:

209

Перейдите в каталог подмодуля, затем выполните команду a, git reset --hardчтобы вернуть все измененные файлы в их последнее зафиксированное состояние. Имейте в виду, что при этом будут отменены все неподтвержденные изменения.

Джейми Пенни
источник
6
Обновление подмодуля git (даже без --init) помогло мне отказаться от «изменений» подмодуля, когда я ничего не изменил. Если вы идете в каталог подмодулей и состояние git отображается пустым, попробуйте это вместо сброса.
Эклектичная ДНК
16
git submodule update --initработал на меня; без --initэтого не сработало вообще.
За Лундберг
Superb !! Я внес изменения в подмодуль в моем репозитории, куда я его импортировал. И это вернуло его обратно к тому, что должно было быть.
Noitidart
2
reset --hard не работал для меня, мой подмодуль все еще не мог быть деиницирован из-за локальных изменений.
Малхал
34
в дополнение к @markshiz, git submodule update -f --initдля моего случая.
otiai10
281

Если вы хотите сделать это для всех подмодулей, без необходимости изменять каталоги, вы можете выполнить

git submodule foreach git reset --hard

Вы также можете использовать рекурсивный флаг для применения ко всем подмодулям:

git submodule foreach --recursive git reset --hard

ворон
источник
7
для автоматизации это работает намного лучше, чем пытаться перейти в каждый подмодульный каталог.
Трэвис Кастильо
4
Обратите внимание, что вы также можетеgit submodule foreach --recursive git clean -x -f -d
йойо
1
на моем компьютере (Windows использует Git 2.22.0) Мне нужно использовать одинарные кавычки вокруг второй команды git при использовании флага --recursive, иначе он не будет работать: подмодуль git foreach --recursive 'git clean -x -f -d'
aatwo
196

Более надежный метод, чем все предыдущие ответы:

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

Первая команда полностью «отменяет привязку» всех подмодулей, а вторая делает новую проверку их.
Это займет больше времени, чем другие методы, но будет работать независимо от состояния ваших подмодулей.

qwertzguy
источник
1
К сожалению, в моем случае это не сработало (с измененными локальными файлами в подмодуле git), команда «update --init» извергаетerror: Your local changes to the following files would be overwritten by checkout
rogerdpack
Чтобы обновить определенный подмодуль, выполните: $ git submodule deinit -f - <submodule_path>, а затем $ git submodule update --init - <
submodule_path
Я попробовал все методы выше, пока не добрался до этого. Для меня, это единственное, что у меня мерзавец ищет «чистый» (без *в моем , PS1что git status -unoне смог объяснить).
Гай Рапапорт
60

Хорошо для меня, имея

git reset --hard

просто сбросьте подмодуль в состояние, в котором он был извлечен, а не обязательно для основного репо, на который ссылается commit / state репо. У меня все еще будет «измененное содержимое», как сказал OP. Итак, чтобы вернуть субмодуль в фиксацию исправлений, я запускаю:

git submodule update --init

Потом, когда я это сделаю git status, в подмодуле все чисто.

контрольная сумма
источник
к сожалению submodule update --init, в любом случае, похоже, не отменять локальные модификации: |
rogerdpack 21.09.16
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
jiahut
источник
2
Единственный, который мне тоже помог.
Виктор Сергиенко,
вопрос, если подмодуль новый, в этом каталоге не будет файла .git, правильно? будет ли команда git отправляться в родительский репозиторий?
Сантьяго Аристи
1
@jiahut Даже после этого у меня все еще есть «(новые коммиты)» рядом с моим подмодулем, когда я делаю «git status» от родителя?
Дэвид Дория
1
@DavidDoria git submodule updateбыло то, что исправило (new commits)для меня.
ubershmekel
31

Это сработало для меня, в том числе рекурсивно в подмодули (возможно, именно поэтому ваш -f не работал, потому что вы изменили подмодуль внутри подмодуля):

git submodule update -f --recursive
Серджиу Тодираску
источник
12

Сначала попробуйте это, как говорили другие:

git submodule update --init

Если это не сработает, перейдите в каталог подмодулей и используйте следующую команду, чтобы увидеть, есть ли какие-либо изменения в подмодуле:

git status

Если есть изменения в вашем подмодуле, избавьтесь от них. Убедитесь, что вы не видите никаких изменений при запуске «git status».

Затем вернитесь в основной репозиторий и снова запустите «git submodule update --init».

Жан Либера
источник
9

Начиная с Git 2.14 (3 квартал 2017 года), вам не нужно заходить в каждый подмодуль, чтобы выполнить git reset(как в git submodule foreach git reset --hard)

Это потому, что сам git reset теперь знает, как рекурсивно войти в подмодули.

Смотрите коммит 35b96d1 (21 апреля 2017 г.) и коммит f2d4899 , коммит 823bab0 , коммит cd279e2 (18 апр 2017 г.) от Stefan Beller ( stefanbeller) .
(Слиты Junio C Hamano - gitster- в фиксации 5f074ca , 29 мая 2017)

встроенный / сброс: добавить переключатель --recurse-submodules

git-reset это еще один рабочий манипулятор дерева, который нужно учить о подмодулях.

Когда пользователь использует git-reset и запрашивает возврат в подмодули, это сбрасывает подмодули на имя объекта, записанное в суперпроекте, отсоединяя HEAD.

Внимание : разница между:

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

Это то, что первый также сбрасывает ваше главное рабочее дерево родительского репо, так как последний сбрасывает только рабочее дерево подмодулей.
Так что используйте с осторожностью.

VonC
источник
7

Для git <= 2.13 эти две команды вместе должны сбросить ваши репозитории с рекурсивными подмодулями:

git submodule foreach --recursive git reset --hard
git submodule update --recursive --init
cmcginty
источник
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   

Хранилище пакетов в LIVE

Здесь мы хотим получить изменения, которые зафиксированы в репозитории 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 foreach 'мастер проверки git && сброс git --hard $ sha1'

alex_1948511
источник