📜 ⬆️ ⬇️

Git time machine

Recently, my colleagues are starting to get acquainted with git. And one of the questions that interests them is how to roll back to a certain revision. On the Internet you can find a set of commands, but I want to have an understanding of each of them. Pampering with git’s commands without understanding can lead to a loss of development history.

In this article I want to talk about the git checkout and git reset commands with the - --soft and - --hard .

So let's start a short educational program on the time machine provided by git. First illustrate the story:


')
Here circles marked commits. The more to the right commit, so it is newer. A commit with a 6e04e hash .. is the very first commit. One of the basic concepts that a newbie should understand is the pointers to commits, or rather, some kind of “nickname” of this or that commit. Their darkness is dark, for example: HEAD, master, FETCH_HEAD, ORIG_HEAD , etc. This I listed a grain of standard nicknames. You can create them yourself, but more on that in front.

Let's focus our attention on two pointers: master and HEAD . master indicates the most senior commit in the branch called master (this branch is created when the repository is initialized). HEAD points to the master pointer (read, the current state of the files). After the first commit appears in the repository, HEAD and master point to the same commit. And it will continue this way until we switch to another branch, roll back through the history, or take a series of rash actions. So, we illustrate our history with pointers:



The HEAD pointer in our case points to master , and the master to the d79fb commit ... It is important to understand that the current state of unchanged files under version control is the commit that HEAD points to. That is, if HEAD points to a commit with hash 6e04e .., then the files will be in their original state. To "move" the HEAD pointer, there is a command: git checkout. Those who are familiar with even a little bit of git, learned in this command switching to another branch. Everything is absolutely true - when switching to another branch, we simply transfer the HEAD pointer to the last commit branch.

Move the HEAD pointer ( git checkout )


Rollback on commit history:



After the checkout operation is completed, we will be in the state in which there were two commitments back. This is all great - we took a step into the past, we peeped at something there, but how could we go back? I, for example, do not have super-memory, and I do not remember the hash of the most recent commit (the one that is the most right is d79fb ..). If we write git log , we will see a story consisting of three commits:
 [user@localhost project]$ git log --pretty=oneline 6741a69bd121c295413be95d7597cd7409e713a0 add unit test b3e74f50c3cc48e6b335014b6dc7e301b382a903 add readme 6e04e39d0952a2d6022502d56aaa05d5a064bea Initial commit 

Have we really lost the whole story? How to find out the most "new" commit? This is not a problem - there is a way out, and there are several:

  1. Write a git log --all command. This command will print the whole story to us, up to the present, i.e. in our case, the story of five commits:
     [user@localhost project]$ git log --pretty=oneline --all d79fb5688af71b4577f450919535e7177e9d74e8 fix bug 478927e3a088d3cec489ca8810eaaca97c6ce0ff documentation 6741a69bd121c295413be95d7597cd7409e713a0 add unit test b3e74f50c3cc48e6b335014b6dc7e301b382a903 add readme 6e04ee39d0952a2d6022502d56aaa05d5a064bea Initial commit 

    Then it remains to copy the hash we need and re-start the time machine: git checkout . But this method is not recommended, because it requires too much action.
  2. Git allows you to track all changes to the HEAD pointer. This is possible with the git reflog , but this is no longer for beginners and is not used for the purposes we have set. The most competent is to do the following:
  3. Recall that the master pointer points to the most recent commit. Thus, a reset is performed by one command: git checkout master . Woo-la:




To clarify the git checkout mechanism, create a new devel branch:
 [user@localhost project]$ git checkout -b devel 

* -b flag means that you need to create a branch with the specified name and immediately switch to it.
We illustrate the action we committed:



Note that the HEAD pointer points to the top of the devel branch.

Let's breed several commits in the new branch. The history of the repository will look like this:



Returning to the master branch is also painless:
 [user@localhost project]$ git checkout master 




So, remember the first item:

Move the pointer to the top of the branch ( git reset ... )


In addition, git allows you to move not only HEAD , but also continents, pointers to the tops of branches. To do this, there is the git reset command with the keys either --soft or --hard .

In both cases, a “nickname” appears for the commit from which the reset was performed - ORIG_HEAD .

git reset --hard HEAD~2 :


git reset --soft HEAD~2 :


ORIG_HEAD is useful for editing incorrect commits on a local machine (!). Suppose we want to merge the last two commits into one. To do this, preserving the current state of the files, we translate the master pointer to two commits ago:
 [user@localhost project]$ git reset --soft HEAD~2 

Let's look at the changes:
 [user@localhost project]$ git status # On branch master # Changes to be committed: # (use "git reset HEAD <file>..." to unstage) # # -    # 

Well, now let's do the trick - combine commits
 [user@localhost project]$ git commit -c ORIG_HEAD 

Enter the message, save. Now our story looks like this:



Important note - ORIG_HEAD still points to the d79fb commit ... If we now execute the git checkout command ORIG_HEAD , we will get the so-called detach HEAD state. It is characterized by the fact that HEAD points not to the top of the branch, but simply to commit. HEAD should always point only to the top of any branch!



To “leave” the state of detach HEAD, you simply switch to a branch or create a new branch with git checkout -b new_branch_name
So, remember the second paragraph:

And the most important thing! The most frequent operation of the above when working with git `th is switching between branches. All other cases considered are rare, but nevertheless it is necessary to understand everything that happens when using them!

Have a nice trip to the history of your repository!

In preparing the material used the following sources:
The best manual book: ProGit
Visual Information on git: A Visual Git Reference ( Russian version )

UPD:
In the comments advised another useful resource on git `y: githowto

PS Thank you for the invite and wish you all a nice weekend!

Source: https://habr.com/ru/post/157175/


All Articles