Ёбаный 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 для каждой испорченной ветки

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

Большое спасибо людям, которые перевели этот сайт на другие языки: Michael Botha (af) · Khaja Md Sher E Alam (bn) · Eduard Tomek (cs) · Moritz Stückler (de) · Franco Fantini (es) · Hamid Moheb (fa) · Senja Jarva (fi) · Michel (fr) · Alex Tzimas (gr) · Elad Leev (he) · Aryan Sarkar (hi) · Ricky Gultom (id) · fedemcmac (it) · Meiko Hori (ja) · Zhunisali Shanabek (kk) · Gyeongjae Choi (ko) · Rahul Dahal (ne) · Martijn ten Heuvel (nl) · Łukasz Wójcik (pl) · Davi Alexandre (pt_BR) · Catalina Focsa (ro) · Daniil Golubev (ru) · Nemanja Vasić (sr) · Björn Söderqvist (sv) · Kitt Tientanopajai (th) · Taha Paksu (tr) · Andriy Sultanov (ua) · Tao Jiayuan (zh) . С дополнительной помощью от Allie Jones · Artem Vorotnikov · David Fyffe · Frank Taillandier · Iain Murray · Lucas Larson · Myrzabek Azil

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