git revert против git reset

Независимо от того, работаете ли вы в одиночку или в команде, вы время от времени будете сталкиваться с ошибочными коммитами в своем проекте Git, которые вам нужно будет отменить. После нескольких ошибок в моих личных проектах из-за использования неправильного решения StackOverflow для сохранения моей работы (в середине панической атаки) я понял, насколько важно различать git revert и git reset и знаете, когда использовать. Для крупных проектов важно знать, как правильно спасти свою работу, чтобы в ней не возникало проблем в долгосрочной перспективе, вместо того, чтобы искать быстрое и грязное решение, которое неизбежно вернется, чтобы преследовать вас в будущем. Ниже я написал несколько распространенных команд Git, которые использую для разных сценариев.

Помощь! Я хочу удалить свои неопубликованные коммиты!

Если вы сделали коммит, но не опубликовали его в удаленном репозитории, вы можете удалить предыдущие коммиты с помощью команды reset. (Примечание: это эффективно, но опасно, так как на «удаленные» коммиты не будут ссылаться или иначе они будут называться «осиротевшими»). Чтобы найти и восстановить эти коммиты без ссылок, используйте команду git reflog. Чтобы быстро найти ссылку на фиксацию / хэш, на который нужно выполнить сброс, найдите его с помощью git log.

Используйте параметр --hard, чтобы включить указатели ссылок на историю фиксации, промежуточный индекс и рабочий каталог как часть процесса удаления. Это означает, что ВСЕ рабочие изменения будут потеряны с этой командой.

РЕШЕНИЕ. Восстановите в локальном файле предыдущую фиксацию (все фиксации после указанной фиксации будут удалены из истории ветки)

git reset --hard <hash-or-ref>
//example: git reset --hard 65806eb

Помощь! Я хочу удалить свои опубликованные коммиты!

Если вы зафиксировали и отправили свой код в удаленный репозиторий, НАСТОЯТЕЛЬНО РЕКОМЕНДУЕТСЯ НЕ использовать git reset, который перезаписывает историю. Самым чистым и безопасным решением является git revert, чтобы файл обновлялся до предыдущего состояния с сохранением истории фиксации ветки. Создается новая ссылка на фиксацию, чтобы отразить эту фиксацию.

РЕШЕНИЕ. Клонирует состояние файла предыдущей фиксации и создает новую фиксацию без изменения истории веток.

git revert <hash-or-ref>
//example: git revert 65806eb
//Accept incoming changes from parent if asked

OR

git revert HEAD
//This reverts to the most recent commit published without using a commit hash or reference

Помогите! Я нажал и случайно сделал git reset вместо git revert, и теперь я не могу нажать на удаленную ветку!

Поскольку вы переписали историю с помощью аппаратного сброса, побочным эффектом является то, что Git больше не может принимать от вас push, потому что ваша новая усеченная локальная ветвь имеет меньшее количество коммитов, чем удаленная ветка. Скорее всего, вы получите следующее сообщение при попытке нажать:

>>Your branch is behind 'origin/main' by n commits, and can be fast-forwarded.

Чтобы обновить удаленную ветку с усеченной версией, необходимо выполнить принудительное нажатие, чтобы HEAD удаленной ветки был сброшен до того же фиксации, что и ваша локальная ветка.

РЕШЕНИЕ. Выполните принудительное нажатие, чтобы перезаписать историю удаленной ветви

git push --force origin <branch-name>
//example: git push --force origin main

Примечание. Если вы работаете в команде, которая обновляет одну и ту же ветку, переписывание истории этой ветки создаст те же проблемы для членов вашей команды, когда они будут тянуть, потому что их ветка будет иметь другую ГОЛОВУ. Для общих веток предпочтительнее использовать git revert вместо того, чтобы очищать историю коммитов с помощью аппаратного сброса.

Помощь! Я внес изменения, которые не фиксировал, но член команды требует, чтобы я исправил срочную ошибку!

Сохраните изменения, сделанные, когда они не были зафиксированы в репозитории, используя git stash, и файл вернется в состояние последней фиксации. Если вы работаете с другой частью файла, обязательно опубликуйте изменения, чтобы они не конфликтовали с сохраненными изменениями.

git stash 
//save staged changes
git stash apply
//apply stashed changes
git stash clear
//delete stashed changes

Это более чистая альтернатива созданию ненужных ветвей и слияний.