Откат на старый коммит Git в публичном репо


802

Как я могу вернуться к конкретному коммиту в git ?

Лучший ответ, который кто-то мог мне дать, это использовать git revertX раз, пока я не достигну желаемого коммита.

Допустим, я хочу вернуться к коммиту, которому уже 20 коммитов, мне придется запустить его 20 раз.

Есть ли более простой способ сделать это?

Я не могу использовать сброс, потому что этот репозиторий является публичным.


1
git revert <commit> не работает?
мику

8
Как указано в моем вопросе, это действительно не поможет мне, если я захочу вернуться к чему-то 20 коммитов назад.
David

7
Этот вопрос очень хорошо ответил здесь stackoverflow.com/questions/4114095/...
user7610

4
Непонятно, что вы подразумеваете под «откатом». Означает ли это, что вы хотите временно переключить свою рабочую копию на определенную ревизию? Или вы хотите навсегда вернуть историю вашего хранилища обратно к определенной ревизии?

1
Вы должны принять ответ и, возможно, проголосовать за любые другие ответы, которые вам нравятся.
Набиль Кадими

Ответы:


1194

Попробуй это:

git checkout [revision] .

где [revision]хеш коммита (например:) 12345678901234567890123456789012345678ab.

Не забудьте .в конце, очень важно. Это применит изменения ко всему дереву. Вы должны выполнить эту команду в корне проекта git. Если вы находитесь в каком-либо подкаталоге, то эта команда изменяет только файлы в текущем каталоге. Тогда совершайте, и вы должны быть хорошими.

Вы можете отменить это,

git reset --hard 

это удалит все модификации из рабочего каталога и промежуточной области.


7
@AlexReisner Этот период в конечных точках каталога, в котором вы находитесь в данный момент, который не обязательно является полным проектом git, правильно? Если бы вы хотели применить изменения ко всему проекту, вы бы вместо этого использовали ': /' как в 'git add: /', если бы вы в настоящее время не были в корне проекта git?
MSpreij

10
примечание: если вы добавили новые файлы в свой проект с тех пор, это не удалит их. Поэтому, когда вы идете на сборку (в зависимости от вашей платформы), вы все равно можете получать ошибки. Удалите новые файлы, и все готово.
TheWestIsThe ...

6
@MSpreij Вы должны выполнить эту команду в корне проекта git. Если вы находитесь в каком-либо подкаталоге, то эта команда изменяет только файлы в текущем каталоге.
volatilevar

3
Здорово, когда вы можете клонировать проект в другом каталоге и использовать git checkout [revision]. вернуться к определенной ревизии, а затем сравнить ее с тем же проектом в другом каталоге. Экономит много времени.
Донато

4
Черт, я забыл "." какой ущерб я нанес своему хранилищу?
Сова

196

Чтобы откатиться до определенного коммита:

git reset --hard commit_sha

Для отката 10 фиксирует назад:

git reset --hard HEAD~10

Вы можете использовать «git revert», как в следующем посте, если вы не хотите переписывать историю

Как вернуть Git-репозиторий к предыдущему коммиту?


4
Единственная разница между этим подходом и «git checkout [revision]». является то, что последний сохраняет ревизии.
Deeshank

53
Этот ответ НЕПРАВИЛЬНЫЙ, так как ОП конкретно заявляет: «Я не могу использовать сброс, потому что этот репозиторий открыт»
Ярин

4
Если репо общедоступно, я думаю, что нет способа откатить коммит в общедоступном репозитории без использования принудительного нажатия (git push -f), так как это повлияет на людей, которые вносили изменения до отката. Таким образом, сброс может быть использован и в локальной песочнице публичного репо.
Нага Киран

4
Это здорово, что это позволяет избежать отсоединения ГОЛОВКИ! Как раз то, что я искал.
кибер-монах

1
В моем случае это сработало, затем используйте «git pull» для быстрой перемотки назад к голове после того, как вы проверили регрессии и т. Д.
Питер Квиринг

86

Ну, наверное, вопрос в том, что вы подразумеваете под «откатом»? Если вы не можете этого сделать, resetпотому что она общедоступна, и вы хотите сохранить историю изменений без изменений, значит, вы хотите, чтобы ваша рабочая копия отражала определенный коммит? Используйте git checkoutи передайте хэш.

Редактировать: Как было отмечено в комментариях, использование git checkoutбез указания ветки оставит вас в состоянии "нет ветки". Используйте, git checkout <commit> -b <branchname>чтобы оформить заказ в филиале или git checkout <commit> .оформить заказ в текущем филиале.


Разве это не ставит вас в странное состояние «В настоящее время не в какой-либо ветви»? Как вы вносите изменения для завершения отката?
Алекс Рейснер

Ну, я просто предлагаю использовать git checkout- он может проверить любую ветку (текущую или новую), какую пожелает. Я обновлю свой ответ, чтобы он не был неоднозначным.
Бен

2
Я попробовал это, но я не думаю, что это правильный способ сделать это, потому что он оставляет стагнацию файлов. Это не удаляет файлы, которых не было в последнем коммите.
David

3
Если вы находитесь в рабочем каталоге и остаетесь в master, вам нужно git resetудалить те файлы, которые, как вы говорите, не хотите делать. Попробуйте сделать это в отдельной ветке: у git checkout <commit> -b <branchname>вас не будет застойных файлов в этой ветке .
Бен

2
Проблема с использованием checkoutзаключается в том, что он не будет удалять файлы, которые были добавлены в предыдущем коммите.

42

Оригинальный плакат гласит:

Лучший ответ, который кто-то мог мне дать, это использовать git revertX раз, пока я не достигну желаемого коммита.

Допустим, я хочу вернуться к коммиту, которому уже 20 коммитов, мне придется запустить его 20 раз.

Есть ли более простой способ сделать это?

Я не могу использовать сброс, потому что это репо публично.

Нет необходимости использовать git revertX раз. git revertможет принять диапазон фиксации в качестве аргумента, поэтому вам нужно использовать его только один раз, чтобы отменить диапазон фиксаций.Например, если вы хотите отменить последние 20 коммитов:

git revert --no-edit HEAD~20..

Диапазон фиксации HEAD~20..короток дляHEAD~20..HEAD и означает «начать с 20- го родителя фиксации HEAD и вернуть все коммиты после него до HEAD».

Это вернет последние 20 коммитов, при условии, что ни один из них не является коммитом слияния. Если есть коммиты слияния, вы не можете отменить их все одной командой, вам нужно будет отменить их индивидуально с помощью

git revert -m 1 <merge-commit>

Обратите внимание, что я тестировал, используя диапазон с git revert использованием git версии 1.9.0. Если вы используете более старую версию git, использование диапазона с git revertможет работать, а может и не работать.

В этом случае, git revert предпочтительнее, чем git checkout.

Обратите внимание, что в отличие от этого ответа, который говорит использоватьgit checkout , git revert фактически удаляются все файлы, которые были добавлены в любой из коммитов, которые вы возвращаете , что делает это правильным способом отменить диапазон ревизий.

Документация


Примечание : это создает новый коммит с отмененными изменениями. Идеально подходит для вопроса ОП. Но убедитесь, что это то, что вы хотите. (Примеры в git-revert doc, ссылки на которые приведены выше, превосходны.) Если вы вместо этого хотите исследовать предыдущие коммиты (т.е. прежде чем выбирать, какой коммит возвращаться), используйте опцию извлечения, упомянутую в других ответах, имея в виду комментарии других сделано по поводу удаленных файлов.
Шерил Хохман

@SherylHohman Возвращение к предыдущему коммиту не создает новый коммит. Я не могу себе представить, что вы имеете в виду здесь.

27

Шаг 1: получить список коммитов:

git log

Вы получите список, как в этом примере:

[Comp:Folder User$ git log
commit 54b11d42e12dc6e9f070a8b5095a4492216d5320
Author: author <author@gmail.com>
Date:   Fri Jul 8 23:42:22 2016 +0300

This is last commit message

commit fd6cb176297acca4dbc69d15d6b7f78a2463482f
Author: author <author@gmail.com>
Date:   Fri Jun 24 20:20:24 2016 +0300

This is previous commit message

commit ab0de062136da650ffc27cfb57febac8efb84b8d
Author: author <author@gmail.com>
Date:   Thu Jun 23 00:41:55 2016 +0300

This is previous previous commit message
...

Шаг 2: скопируйте необходимый хеш коммита и вставьте его для проверки:

git checkout fd6cb176297acca4dbc69d15d6b7f78a2463482f

Это все.


11
git read-tree -um @ $commit_to_revert_to

сделаю это. Это "git checkout", но без обновления HEAD.

Вы можете достичь того же эффекта с

git checkout $commit_to_revert_to
git reset --soft @{1}

если вы предпочитаете объединять удобные команды вместе.

Это оставит вас с вашим рабочим деревом и индексом в желаемом состоянии, вы можете просто git commitзакончить.


Это единственный простой подход, который работал как шарм! Я извлек из головы, выполнил эту команду, и она успешно удалила добавленные файлы, которые мы ввели, и отменила все изменения. Отлично.
kamranicus

6

Хотите HEAD отдельный режим?

Если вы хотите откатить время X до определенного коммита с DETACHED HEAD (то есть вы ничего не можете испортить), тогда непременно используйте следующее:

(замените X на количество коммитов, которые вы хотите вернуться)

git checkout HEAD~X

IE, чтобы вернуться на один коммит:

git checkout HEAD~1

1
Я бы удалил часть с ... трудно поверить ... Это кажется личным, а также кто-то упомянул об этом в комментарии выше, и в @ken тоже в своем ответе.
meJustAndrew

@meJustAndrew Это так много ответов о SO, который просто смущает людей, это довольно раздражает.
Карл Моррисон

Какой простой и прямой ответ.
Аммад

2

Допустим, вы работаете над проектом и через день или около того. Вы заметили, что одна функция все еще дает вам ошибки. Но вы не знаете, какое изменение вы сделали, что привело к ошибке. Таким образом, вы должны ловить рыбу предыдущих рабочих коммитов. Чтобы вернуться к определенной фиксации:

git checkout 8a0fe5191b7dfc6a81833bfb61220d7204e6b0a9 .

Итак, этот коммит работает на вас. Нет больше ошибок. Вы определили проблему. Теперь вы можете вернуться к последнему коммиту:

git checkout 792d9294f652d753514dc2033a04d742decb82a5 .

И извлеките конкретный файл, прежде чем он вызвал ошибку (в моем случае я использую пример Gemfile.lock):

git checkout 8a0fe5191b7dfc6a81833bfb61220d7204e6b0a9 -- /projects/myproject/Gemfile.lock

И это один из способов обработки ошибок, созданных вами в коммитах, без осознания ошибок на потом.


2

Вы можете найти идентификатор коммита, связанный с каждым коммитом, в разделе коммитов GitHub / BitBucket / Gitlab. Это очень просто, предположим, ваш идентификатор коммита 5889575, а затем, если вы хотите вернуться к этой части в вашем коде, вам просто нужно набрать

git checkout 5889575 .

Это приведет вас к этому моменту в вашем коде.


1

Я не уверен, что изменилось, но я не могу оформить конкретный коммит без опции --detach. Полная команда, которая работала для меня, была: git checkout --detach [commit hash]

Чтобы вернуться из отключенного состояния, я должен был оформить заказ в местном отделении: git checkout master


Выезд masterрешает проблему оставаться отстраненным, пока он работает git reset --hardили git checkout -- .работал, но остался отстраненным
DarkCygnus

0

Вот пример, чтобы сделать это

    cd /yourprojects/project-acme 


    git checkout efc11170c78 .
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.