# Git Advanced-2

# Git Revert & Reset

## Git Revert

**What is Git Revert?**

`$ git revert commitID` : As the name suggests it is something like going back. In the context of Git, revert works as an **undo** mechanism. It helps to go back or undo a step if made wrong however, it is not a traditional undo.

### What's so special about Revert?

**Revert** is a step ahead of traditional undo operation. Instead of removing the commit from the history, it finds out how to invert the changes introduced by the commit.

It requires the commit id which we can get from the git log by the command `$ git log --oneline` .

## Illustration

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1673451037475/4f0eb47e-3632-4a81-8a71-e7200e2d6b2a.png align="left")

In the above picture, you can see we have 3 files and 4 commits. The last commit was some changes to the **thirdFile.txt** with the commit id `cc2fe9d`

Suppose, unknowingly we have made some mistakes while making changes to **thirdFile.txt** and we want to undo that mistake by revert operation.

**The content of thirdFile.txt before the revert was as below:**

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1673451260874/94555c61-43a3-4636-9ba2-fe3ec2ec44dd.png align="left")

`$ git revert cc2fe9d` : This command will revert the last commit that was made with the specified commit id. After hitting the command it will prompt for the revert you are proceeding for as below which is similar to **git message** here you can specify any customized message you want to log during the revert operation:

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1673451536476/6b2c3fe6-a508-4cb7-8151-bd73d25fd8ef.png align="left")

**The content of thirdFile.txt after the revert will be as below:**

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1673451719844/7e3c0119-b36e-4d0d-9b4a-44a0c90cedb9.png align="left")

Here, **"adding some lines for reverting"** is undone in the above picture.

And now if we recheck the log as shown below picture with the command `$ git log --oneline` we can see that another **hashId** `844bca4is` generated for the revert operation without impacting the previous log of commit ids even the commit id `cc2fe9d` is still intact which is the difference between **traditional undo and git revert.**

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1673451985929/8931c8f1-fd13-4b65-a7d1-ebf06e968175.png align="left")

**NB**: `$ cat thirdFile.txt` : cat is the Linux command to display the content of a file.

## Can a file be deleted with Revert command?

Technically the answer is **no**. Revert command **undoes** the commit you specify as **hashId .** So whatever operation has been performed with that hashid will be undone.

Let's understand the below scenario:

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1673456963005/7acad77f-c291-4bc3-8be6-3b49b341bf80.png align="left")

Above picture, we can see that we have **5 commits** until now out of which the commitID `b87dfa5` is logged for adding **the Second file** so by this commit a new file was added or created on the master branch before that the file was not present hence, the sole purpose of this particular commit is to create that file. So, when we performed `$ git revert b87dfa5` it reverted to its previous state(deleted) the file that was created against the commitID. Hence, the **revert** operation considers every action as a commit and undoes whatever was done whether it's a code change or file creation it simply brings the operation **one step back.**

Now you can see logs are still intact. The revert action that deleted the SecondFile is also logged with a hasID or commit ID:

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1673457452487/a3feb31c-3141-4f5f-9583-5b2a7fb74b00.png align="left")

Hence, we can say that **"Everything we do in Git is a Commit".**

## Git Reset

**Git Reset** is a very important and versatile tool when it comes to **undoing** changes or mistakes. It has three primary forms of invocation. These forms correspond to command-line arguments `--soft` and `--hard` .

Git Reset has a benefit over Git Revert which is, it completely cleans the entire log whereas Git Revert keeps a log of the reverted commit as well.

## Illustration

To understand this we will create another separate branch to keep our master branch intact where we will create several files and take the created branch ahead of the master branch. Now in the below picture, you can see currently we have 2 files **firstFile.txt and thirdFile.txt.**

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1673459848786/ec3f37aa-848a-445a-9120-124e86cd3e2c.png align="left")

Now, we have added one more file as **SecondFile.txt** in our newly created branch and have done some incremental commits which you can see below:

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1673460409803/fc900492-51f0-4509-a959-0ccf0108b1c1.png align="left")

**Consider a scenario:**

Suppose after doing the above 3 to 4 commits you realized that there are some unstable codes you have committed and now you want to delete the commits you made as well as you don't even want to keep a single trace/log of previous commits. Here comes the command `$ git reset --soft`

`$ git reset --soft commitID` : This command will help you with the above scenario. It will clear all the commits, modifications made and even the log of the commits that are performed **after** the **specified commitID.**

All the mess is done right after the commitID will be cleared.

Now, have a look at the below picture to understand the difference made with the reset operation. Here the command `$ git reset --soft 94347b5` has cleaned all the commits that were made on **branch1** previously upto `94347b5` :

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1673460972113/7d5d0260-1375-4d64-b3ef-488470556065.png align="left")

## Git Revert vs Git Reset

It's important to understand that `git revert` undoes a single commit—it does not "revert" back to the previous state of a project by removing all subsequent commits. In Git, this is called a reset, not a revert.

Reverting has two important advantages over resetting.

First, it doesn’t change the project history, which makes it a “safe” operation for commits that have already been published to a shared repository.

Second, `git revert` can target an individual commit at an arbitrary point in history, whereas `git reset` can only work backward from the current commit.

`git revert` is a safer alternative to `git reset` in regards to losing work.

# Cherry-Pick

Cherry-Pick is a very powerful command that enables us to pick any arbitrary commit from any branch and **append** it to the working head. It picks the commit by reference.

In layman's terms, we can say that it moves a commit from one place and **append at the current working HEAD**.

### Cherry-Pick Usecase

Suppose you have made some changes in a file and committed to the wrong branch. However, now you realized and want to undo it and move that particular commit to the right branch. This is where cherry-pick kicks in.

To perform cherry-pick, make sure you switch to the correct branch and cherry-pick the commit to where it should belong.

### Illustration

Now let's say we have two branches **master** and **branch1.** Total 8 commits are combining all the branches as below:

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1673491257291/be89d6e1-ced5-402c-80cc-bee6a1bd5ba1.png align="left")

After committing the last commit which is `b5416e5 (HEAD -> branch1) Fixing the bug in SecondFile` , you realized this commit needs to be done in the **master** branch as part of a bug fix. In that case, you have to cherry-pick this particular commit with it's reference `b5416e5` .

To do so we first need to switch to the branch into which `b5416e5` will be cherry-picked.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1673491539849/59c40bd8-bf72-48e8-b8a6-6c64c16c3d57.png align="left")

Now, as we have moved to the **master** branch using `$ git checkout master` let's perform **cherry-pick** as below:

`$ git cherry-pick commitID` : It will pick the specified commit and append to the master branch as the latest commit as **below,** now you can see the commit `cea35d5` which was previously on **branch1** is now appended to **master as the** latest commit.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1673492257101/079e473c-f739-4562-833d-fb9b536ec411.png align="left")

**Condition: What if there is any conflict?**

If during cherry-picking any **conflict arises** as **blow**, we first need to resolve the conflict then only we can proceed with cherry picking.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1673492570348/8bbdf118-072b-4e74-911c-595703b8b3dc.png align="left")

Read through the conflicted file using `$ vim filename` . By doing vim you will be prompted with details about the conflicts and will be able to resolve them.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1673492715736/ae7aeba9-c4c8-4d8f-8907-0d7b284b0714.png align="left")

After resolving the conflicts you can be able to succeed with cherry-picking as below, here I resolved the conflicts by committing uncommitted files :

**NB:** Conflicts can vary or you may not face any conflicts at all. But in real scenarios we mostly face conflicts as lot of changes, fixes gets done by multiple developers

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1673492884503/9f53bba4-d3bd-461e-94a0-6da4ce59364a.png align="left")

# Summary:

Cherry picking is a powerful and convenient command that is incredibly useful in a few scenarios. Cherry picking should not be misused in place of git merger or git rebase.

The `git log --oneline or git log` commands are required to help find commits to cherry-pick.
