Git how to cancel commit
Git how to cancel commit
Отмена коммитов и изменений
В этом разделе мы обсудим доступные стратегии и команды Git для выполнения отмены изменений. Прежде всего необходимо отметить, что в Git не существует традиционной системы отмены, как в текстовых редакторах. Лучше воздержаться от сопоставления операций Git с какой бы то ни было традиционной концепцией отмены изменений. Кроме того, Git имеет собственную систему терминов для операций отмены, и в обсуждении лучше всего использовать их. В числе таких терминов — сброс (reset), возврат (revert), переключение (checkout), очистка (clean) и другие.
Git можно рассматривать как инструмент для управления временной шкалой. Коммиты — это снимки моментов времени или точек интереса на временной шкале истории проекта. Кроме того, с помощью веток можно управлять несколькими временными шкалами. Когда вы выполняете операцию отмены в Git, вы, как правило, перемещаетесь назад во времени или на другую временную шкалу, где ошибок не было.
Это руководство предоставляет все необходимые навыки для работы с предыдущими версиями проекта по разработке программного обеспечения. Сначала мы рассмотрим, как исследовать старые коммиты, а затем изучим разницу между отменой публичных коммитов в истории проекта и сбросом неопубликованных изменений на локальном компьютере.
Поиск утерянного: просмотр старых коммитов
Просмотр старых версий
В этом примере предполагается, что вы начали разработку безумного эксперимента, но не уверены, хотите его сохранить или нет. Чтобы принять решение, вы хотите взглянуть на состояние проекта до начала эксперимента. Прежде всего, нужно найти идентификатор редакции, которую вы хотите просмотреть.
Допустим, история вашего проекта выглядит примерно так:
Для просмотра коммита «Make some important changes to hello.txt» можно использовать команду git checkout в следующем виде:
Предположим, вы ведете разработку в главной ветке main по умолчанию. При каждом возвращении в ветку main можно использовать команду git revert или git reset для отмены нежелательных изменений.
Отмена коммита снимка
Технически существует несколько стратегий отмены коммитов. В дальнейших примерах предполагается, что история коммитов выглядит следующим образом:
Отмена коммита с помощью git checkout
Отмена публичного коммита с помощью git revert
Отмена коммита с помощью git reset
Отмена последнего коммита
Отмена неотправленных изменений
Рабочий каталог
Раздел проиндексированных файлов
Отмена публичных изменений
Резюме
Помимо основных команд отмены, мы рассмотрели другие команды Git: git log для поиска потерянных коммитов, git clean для отмены изменений, не подтвержденных коммитами, и git add для изменения индексирования.
Каждая из этих команд имеет собственную подробную документацию. Чтобы узнать больше о той или иной команде, пройдите по соответствующим ссылкам.
Как отменить commit и не облажаться
Возьмем простую ситуацию: разработчик решает реализовать математические функции. Но на половине пути понимает, что данную задачу было бы хорошо декомпозировать, допустим, на две подзадачи:
Проверять будет проще да и тестировать. Но он уже начал ее реализовывать, коммиты уже созданы, и что же делать? Не переписывать же!
git revert
Работа кипит и осталось дело за малым — смерджить мастер с данными ветками.
И что же мы получили? Ни класса Arithmetic, ни класса Numerical!
А все дело в том, что команда git revert создает новый коммит с отменой изменений и не удаляет из истории коммиты. И в нашем случае после слияния веток получается 4 коммита:
То есть вариант с отменой изменений с помощью команды revert вышел нам боком.
git reset
git rebase
Есть еще одно решение — использовать команду git rebase для отмены изменений.
Вернемся к моменту создания двух веток numerical и arithmetic и выполним
Теперь на уровне каждого коммита, который мы хотим отменить заменим pick на drop. И тогда выбранные нами коммиты сбросятся из истории. Например в ветке numerical :
Тогда в истории у нас останутся только нужные нам коммиты.
Теперь при слиянии веток в master получим оба класса.
Данный метод рабочий, только при условии работы в частной ветке, но если эти манипуляции провести в общей ветке, то при публикации ( git push ) git сообщает, что ветка устарела, так как в ней отсутствуют коммиты и отменяет публикацию.
Чтобы не бороться с git, старайтесь декомпозировать задачи заранее, а то можете словить сюрприз. Сталкивались ли вы с такими ситуациям, и если да, то как выходили из них?
How to cancel a local git commit?
My issue is I have changed a file e.g.: README, added a new line ‘this for my testing line‘ and saved the file, then I issued the following commands:
I didn’t push the code to GitHub. Now I want to cancel this commit.
For this, I used
But I lost the newly added line ‘this for my testing line‘ from the README file. This should not happen. I need the content to be there. Is there a way to retain the content and cancel my local commit?
7 Answers 7
Trending sort
Trending sort is based off of the default sorting method — by highest score — but it boosts votes that have happened recently, helping to surface more up-to-date answers.
It falls back to sorting by highest score if no posts are trending.
Switch to Trending sort
PS: On Unix based systems you can use HEAD^ which is equal to HEAD
It will remove the last local (unpushed) commit, but will keep changes you have done.
So you can delete all lines so that the commit message is empty, then save the file:
The first thing you should do is to determine whether you want to keep the local changes before you delete the commit message.
Use git log to show current commit messages, then find the commit_id before the commit that you want to delete, not the commit you want to delete.
If you want to keep the locally changed files, and just delete commit message:
If you want to delete all locally changed files and the commit message:
That’s the difference of soft and hard
You can tell Git what to do with your index (set of files that will become the next commit) and working directory when performing git reset by using one of the parameters:
—soft : Only commits will be reseted, while Index and the working directory are not altered.
—mixed : This will reset the index to match the HEAD, while working directory will not be touched. All the changes will stay in the working directory and appear as modified.
—hard : It resets everything (commits, index, working directory) to match the HEAD.
How do I delete unpushed git commits?
I accidentally committed to the wrong branch. How do I delete that commit?
7 Answers 7
Trending sort
Trending sort is based off of the default sorting method — by highest score — but it boosts votes that have happened recently, helping to surface more up-to-date answers.
It falls back to sorting by highest score if no posts are trending.
Switch to Trending sort
Delete the most recent commit, keeping the work you’ve done:
Delete the most recent commit, destroying the work you’ve done:
I wonder why the best answer that I’ve found is only in the comments! (by Daenyth with 86 up votes)
This command will sync the local repository with the remote repository getting rid of every change you have made on your local. You can also do the following to fetch the exact branch that you have in the origin as Cleary suggested in the comments.
Don’t delete it: for just one commit git cherry-pick is enough.
Suppose you have this:
, then you can mark master and move it where you would want to be:
, reset y branch where it should have been:
, and finally move your commits (reapply them, making actually new commits)
If you want to move that commit to another branch, get the SHA of the commit in question
Then switch the current branch
And cherry-pick the commit to other-branch
Following command worked for me, all the local committed changes are dropped & local is reset to the same as remote origin/master branch.
In fact, if you don’t care about checking out, you can set the branch to whatever you want with:
This would be a programmatic way to remove commits from a branch, for instance, in order to copy new commits to it (using rebase).
Suppose you have a branch that is disconnected from master because you have taken sources from some other location and dumped it into the branch.
You now have a branch in which you have applied changes, let’s call it «topic».
You will now create a duplicate of your topic branch and then rebase it onto the source code dump that is sitting in branch «dump»:
Now your changes are reapplied in branch topic_duplicate based on the starting point of «dump» but only the commits that have happened since «master». So your changes since master are now reapplied on top of «dump» but the result ends up in «topic_duplicate».
You could then replace «dump» with «topic_duplicate» by doing:
Or just by discarding the dump
Perhaps you could also just cherry-pick after clearing the current «topic_duplicate».
Rebasing only works on a branch that already has the commits, so you need to duplicate your topic branch each time you want to do that.
Cherrypicking is much easier:
So the entire sequence will come down to:
When your topic-duplicate branch has been checked out. That would remove previously-cherry-picked commits from the current duplicate, and just re-apply all of the changes happening in «topic» on top of your current «dump» (different ancestor). It seems a reasonably convenient way to base your development on the «real» upstream master while using a different «downstream» master to check whether your local changes also still apply to that. Alternatively you could just generate a diff and then apply it outside of any Git source tree. But in this way you can keep an up-to-date modified (patched) version that is based on your distribution’s version while your actual development is against the real upstream master.
So just to demonstrate:
Hope this helps someone. I was meaning to rewrite this, but I cannot manage now. Regards.
Полезные команды Git: безопасная отмена коммитов, добавление файла из другой ветки и другие
Git — это мощный, хотя и незамысловато выглядящий, инструмент, который при неосторожном использовании может устроить большой беспорядок. Поэтому, прежде чем пробовать выполнять различные фокусы с Git, я рекомендую ознакомиться с его основными командами (init, clone, push, pull, status, log и т.д.) и концептами (репозиторий, ветвь, коммит, и т.д.).
Итак, если вы уверенно чувствуете себя при работе с Git, вот несколько полезных трюков, о которых я знаю.
Reflog. Отмена операций
Я помню, что в начале знакомства с Git я боялся запускать команды. Я думал, что всё испорчу. Например, первое использование git rebase вызвало у меня несколько восклицаний наподобие «Вот *****! Что я только что сделал?!» из-за дублировавшихся или вообще исчезнувших коммитов. Вскоре после этого я понял, что нужно идти дальше.
Лично я не люблю использовать инструмент, не зная, что именно он делает для достижения результата. Это как вождение машины без руля: всё прекрасно до тех пор, пока не доедешь до поворота. А что потом? Ну, вы меня поняли.
или относительную ссылку:
и вы окажетесь в независимом (detached) состоянии HEAD, из которого можно создать новую ветвь.
Вот и всё. Все операции после вышеуказанного состояния отменены.
Revert. Отмена изменений коммита
Вы, должно быть, сталкивались с ситуацией, когда вам нужно было отменить некоторые изменения. На помощь придёт команда revert :
Что она делает? Она просто отменяет действия прошлых коммитов, создавая новый, содержащий все отменённые изменения. Зачем использовать её вместо других решений? Это — единственный безопасный способ, так как он не изменяет историю коммитов. Он обычно используется в публичных ветвях, где изменение истории нежелательно.
Давайте взглянем на другие команды, способные отменять действия.
Rebase
Вы можете выполнить эту команду и просто убрать строки, относящиеся к ненужным коммитам. Это самое очевидное и простое решение, но у него есть недостаток, из-за которого его нельзя использовать в публичных ветвях: он изменяет историю коммитов. Поэтому после rebase’а у вас может возникнуть проблема с push’ем.
Reset
Эта команда удаляет все коммиты выше указанного. Она лучше предыдущей тем, что не добавляет новую информацию в историю, но тем не менее тоже ее меняет.
Checkout
Эта команда откатывает выбранный файл к состоянию в более ранней версии указанного коммита. Отменённые изменения будут в рабочей директории, и их можно будет закоммитить как угодно.
Вывод таков, что git revert — самая безопасная операция для отмены действий. Кроме того, нужно заметить, что эти команды не взаимозаменяемы в 100% случаев.
Log. Более приятное форматирование
С git log всё просто. Вы вводите команду и видите историю коммитов в хронологическом порядке, и каждый пункт включает в себя хэш коммита, автора, дату и прикреплённое сообщение.
Давайте взглянем на вид лога по умолчанию:
Я думаю, что могло бы быть и лучше.
Я предпочитаю простые вещи. Поэтому я использую две опции:
Вот как это выглядит:
Тем не менее, иногда нам нужно знать дату и автора коммита. В таких случаях я использую следующее:
Ничего себе! Давайте посмотрим, как это выглядит:
И всё-таки вводить эти команды каждый раз достаточно неудобно, так? Давайте создадим алиасы. Я считаю, что использование алиасов очень сильно повышает продуктивность. Чтобы зарегистрировать их, добавим следующие строки в «
/.bash_profile» (конечно, если вы используете *nix OS):
Еще один вариант украшения вывода лога приведен в этой статье.
Diff. Разница между коммитами
Другой — вывод всех изменений, не внесённых в индекс. Для этого нужно выполнить следующее:
Branch. Проверка ветвей на слияние
Я думаю, вы уже знаете, что делает базовая команда git branch (без опций выводит список локальных веток — прим. перев.), поэтому перейдём к делу. Время от времени вам понадобится удалять старые или ненужные ветви из вашего «дерева» git.
вы получите список всех веток, соединённых с текущей.
Можно и наоборот:
Так вы получите список всех не соединённых с текущей веток.
Таким образом, вы всегда узнаете, безопасно ли удаление той или иной ветви.
Checkout. Получение файла из другой ветви
Указанный файл будет приведен к версии, указанной в заданном коммите. Раньше мы использовали это для отмены изменений файла. Удобно то, что этот коммит необязательно должен находиться в той же ветви, что и наш файл. Поэтому мы можем задать любому файлу любую версию из любого коммита или ветви.
Надеюсь, вы нашли здесь для себя что-то полезное. Прошу заметить, что все вышеуказанные моменты субъективны, поскольку я подгонял их под свои нужды.