Ёбаный Git!!!

Git сложен: легко все проебать, и нереально сложно понять, как все исправить. Документация Git это такая вещь, в которой сложно найти решение, если только ты точно не знаешь название фишки, которая вернет все на место.

Так, здесь собраны несколько ситуаций, из которых я в конце концов выбрался на понятном русском.

Бля, я сделал что-то ужасное, пожалуйста скажите у git есть волшебная машина времени!?!

git reflog
# вы увидите список всего, 
# что сделали в git, во всех ветках!
# у каждого элемента есть индекс HEAD@{индекс}
# найдите тот, перед которым все сломалось
git reset HEAD@{index}
# волшебная машина времени

Вы можете использовать это чтобы вернуть случайно удалённые штуки, или убрать то, что вы пытались сделать, но это все сломало, или восстановиться после неудачного слияния, или просто вернуться назад ко времени, когда все работало. Я использую reflog ОЧЕНЬ МНОГО. Снимаю шляпу перед теми, кто предложил добавить это.

Бля, Я закоммитил и внезапно понял, что нужно сделать маленькое изменение!

# сделайте своё изменение
git add . # или добавьте файлы по отдельности
git commit --amend --no-edit
# теперь ваш последний коммит содержит это изменение!
# ПРЕДУПРЕЖДЕНИЕ: никогда не меняйте опубликованные коммиты!

Обычно я это использую, когда коммичу, потом запускаю тесты/сканеры... и угх, я не поставил пробел после знака равно. Так же можно сделать изменения в новом коммите и использовать rebase -i чтобы склеить оба коммита вместе, но так в миллион раз быстрее.

Предупреждение: Вы никогда не должны изменять коммиты, которые были выгружены в публичную ветку! Изменяйте только те коммиты, которые находятся лишь в вашей локальной ветке, иначе вам будет хреново.

Бля, мне нужно изменить сообщение моего последнего коммита!

git commit --amend
# открывает редактор для смены сообщения

Ёбаные требования по наименованию.

Бля, Я случайно закоммитил что-то в мастер, хотя это должно быть в новой ветке!

# создаст новую ветку из текущего состояния мастера
git branch какое-то-имя-новой-ветки
# удалит последний коммит из мастера
git reset HEAD~ --hard
git checkout какое-то-имя-новой-ветки
# ваш коммит тепрь живет в этой ветке :)

NB: это не будет работать, если вы уже выгрузили коммит в удалённую ветку, и если вы пробовали сделать это как-то по-другому, может помочь git reset HEAD@{количество-коммитов-назад} вместо HEAD~. Ёбушки-воробушки. Так же многие люди предлагали сделать тоже самое, но короче. Спасибо всем!

Бля, я случайно закоммитил не в ту ветку!

# отменяет последний коммит, но оставляет изменения доступными
git reset HEAD~ --soft
git stash
# переключиться на нужную ветку
git checkout имя-нужной-ветки
git stash pop
git add . # или добавьте отдельные файлы
git commit -m "ваше сообщение здесь"
# теперь ваши изменения на нужной ветке

Многие люди предлагали использовать cherry-pick в такой ситуации, так что выбирайте, то что вам больше нравится!

git checkout имя-нужной-ветки
# скопировать последний коммит из мастера
git cherry-pick master
# удалить из мастера
git checkout master
git reset HEAD~ --hard

Бля, я пытаюсь запусить diff но ничего не происходит?!

Если вы уверены, что изменили файлы, но diff пуст, возможно вы индексировали изменения (add) и нужно использовать специальный флаг.

git diff --staged

¯\_(ツ)_/¯ (да, я знаю, что это не баг, а фича, но это нихуя не очевидно с первого раза!)

Бля, мне нужно отменить коммит, который был 5 коммитов назад!

# найдите коммит, который нужно отменить
git log
# используйте стрелочки, чтобы прокрутить историю
# сохраните хеш нужного коммита
git revert [сохранённый хеш]
# git создаст новый коммит, отменяющий выбранный
# отредактируйте сообщений коммита
# или просто сохраните

Вам не нужно откатываться назад и копипастить старый файл в существующий! Если вы закоммитили баг, можно его убрать с revert.

Так же можно отменить только один файл вместо целого коммита! Но конечно, (как всегда у git`а) это совершенно другой набор чёртовых команд...

Бля, мне нужно отменить изменения в файле!

# найти хеш коммита, до которого нужно откатиться
git log
# используйте стрелочки, чтобы прокрутить историю
# сохраните хеш нужного коммита
git checkout [сохранённый хеш] -- путь/к/файлу
# старая версия файла окажется в вашем индексе
git commit -m "Ого, теперь не придётся копипастить, что бы отменить изменения!"

Когда я наконец понял это, это было ОХУЕННО. Говоря серьезно, где в этой чёртовой вселенной checkout -- лучший способ отменить изменения? :угрожает-линусу-торвальдсу:

Нахуй всё, я сдаюсь.

cd ..
sudo rm -r чёртов-репозиторий-git
git clone https://some.github.url/чёртов-репозиторий-git.git
cd чёртов-репозиторий-git

Спасибо Eric V. за эту подсказку. Все жалобы по поводу использованию sudo в этой шутке могут быть направлены сразу ему.

Вообще говоря, если ваша ветка настооолько загажена, что нужно вернуться к удалённому состоянию в "git-корректном стиле" попробуйте это, но это необратимо!

# получить последнее состояние origin
git fetch origin
git checkout master
git reset --hard origin/master
# удалить неиндексированные файлы
git clean -d --force
# повторить checkout/reset/clean для каждой испорченной ветки

*Предупреждение: Этот сайт не является исчерпывающим руководством. И да, есть другие способы сделать тоже самое, но я пришел к этому методом проб и ошибок, и теперь делюсь этим с большой дозой легкомыслия и ругани. Примите это или уйдите!

Большое спасибо людям, который перевели этот сайт на другие языки: Moritz Stückler (de) · Daniil Golubev (ru) · Łukasz Wójcik (pl) · fedemcmac (it) · Michel (fr) · Andriy Sultanov (ua) · Meiko Hori (ja) · Alex Tzimas (gr) · Franco Fantini (es) · Catalina Focsa (ro) · Davi Alexandre (pt_BR) . С дополнительной помощью от Iain Murray · Frank Taillandier · David Fyffe · Lucas Larson

Если вы хотите добавить перевод на свой язык, отправьте PR на GitHub