Git yourself some cool new tricks
Tags: git, terminal
Published: 2020-09-12 22:15:21

---
title: Git yourself some cool new tricks
published: true
description: Explore some different ways of doing usual things while using git in the terminal
tags: #git #terminal
cover_image: https://blog.cpanel.com/wp-content/uploads/2018/05/image2018-2-8_17-46-1.png
---

Hello friends!

This time we'll be talking about some various ways that we can use to do common tasks with Git on the terminal.

We'll understand more about Git functionality and also add some new tricks to our toolbox when using it to manage changes in our local workspace and in GitHub (or GitLab, Bitbucket, etc.)

So if you are ready to get started, let's dive right into it!

![Diving into a pool](https://media.giphy.com/media/3oxHQgGYs3u7TcrnbO/giphy.gif)

## The basics 

For most of us, we are already familiar with the common workflow of git which is something like...

_Pull latest changes from remote repo, work on the code, add our changes, commit them and push them to the remote repo_

Since normally the bulk of the work doesn't happen in the master branch, we use feature branches which can be created with the command  

```git
git branch {branchName}
``` 

and then we can move to the recently created branch, or we could use everyone's favorite shortcut 

```git
git checkout -b {branchName}
```

Using branches it's when Git becomes more interesting. The branches can exist both in the remote repo and also in our local copy of it 

Normally, we create the branches locally and then push them to the remote repo although we can also create them the other way (i.e. from the remote and them pull them locally.)

Now, how do we know what branches exist and whether or not they have a matching remote branch? 

First let's make sure that we _actually_ have a remote repo linked to our local one. We can check that with the  `git remote` command. 

Although it's more useful when we use the `--verbose` flag or `-v` for short like so 

```git
git remote -v
```

Once we know we have a remote repo, we can see the existing branches on our local with `git branch` which will list all branches created. 

![git branch](https://dev-to-uploads.s3.amazonaws.com/i/9vdn6hrh75b1uw1ttsj6.png)

We can get more info about them with the `-v` flag that will show us the id and name of the last commit made on that branch.

![git branch -v](https://dev-to-uploads.s3.amazonaws.com/i/v7830xceqtxixczhwo8s.png)

And we can get _even more_ info on the branches with the `-vv` flag that will show us not only the info of the last commit but also the name of the remote branch the local one is pointing to (if it has one.)

![git branch -vv](https://dev-to-uploads.s3.amazonaws.com/i/6y8xkxjk2siv43ws9258.png)


## Taking things up a notch 

Now,  we know how to create branches and move to them once created. 

In order to navigate between different branches we would have to use the `git checkout` command and the name of the branch. 

Though there's a nifty little trick to navigate back and forth between two branches without having to write their names every time. To do so, use the command

```git
git checkout -
```

Once we make changes to a file, we can save it to the **working directory**, add it to the **staging area** and then make a commit before pushing it up to the remote. 

There are several things we can do once we have changes committed to the Git history (like being able to recover changes if something unwanted happens for instance)

The standard command for that is `git commit` which if used alone will open the Git default editor so that we can introduce a commit message.

You can also tell Git which editor you want it to use as a default by running the command 

```git
git config --global core.editor "your_editor_of_choice"
```

In my case I use Vim (_the grandfather of all text editors_) but you can use nano, emacs and even VSCode.

Now, let's assume we created a commit with a generic message (because we were trying out the editor config) and now we want to change that message for something more descriptive. To do that, run the command 

```git
git commit --amend -m "More descriptive commit message" 
```

And now a new commit will be created with the message we provided, we could now be ready to push our changes to the remote repo... 

**But...** did you know that the amend flag also works to add additional changes that we may have forgotten and should've been part of the previous commit?

In that case we have to add the changes before amending the commit with `git add . `or  `git add -A` which is the shorthand for `--all` .  

### Difference between `git add .` & `git add -A` 

The difference relies in that `git add .` only adds files in the current directory where you're located whereas `git add -A` add the files in the current **and** in any subdirectories as well, hence the "all".

Ok, we added the necessary files, commited them and now we're ready to push them to the remote. We do so with the command 

```git
git push origin {branchName}
```
If it's the first time we're pushing this branch to the remote, we can pass in the `--set-upstream` flag or `-u` for short like so

```git
git push -u origin {branchName}
```

And now, every time we want to push new changes from that same branch we can just run `git push` and Git will know what remote we're talking about. 

We can now see the commit history in the remote repo navigating to the URL we see when running the `git remote -v` command.

### Undoing changes pushed to a remote

Now let's assume that we pushed the commit to the wrong branch (maybe because we were so busy paying attention to the difference between the flags to pass to git add...)

Don't worry we can fix that issue with the `git revert` command.

Suppose we have the following history in our `git log`

![git log](https://dev-to-uploads.s3.amazonaws.com/i/1j7bxkbtgw74t9t5817w.png)

And we want to remove that last commit from the branch that is on and maybe move it to a different one.

In that case we would run the revert command like this.

```git
git revert 0a995a8
```

And now Git will create a _revert_ commit with the changes of the previous commit undone. 

(You could also have used 'HEAD' instead of the id of the commit with the same result, but I think it's easier to understand what Git is doing using ids instead of pointers to commits.)

What's left to do now is to push this new revert commit to the remote (and if you work with others, tell them to do a pull so they can get the fix.) 

That wasn't too bad was it? although if we want to be more cautious for next time, we can avoid doing a revert commit and handle the commits locally.

### Moving a commit from one branch to another

Let's see how we can move a commit. There are a couple of ways of doing it, like most things in Git. 

Let's imagine that we are in the 'feature/about' branch and we found something to fix in the contact section and committed it there. 

We'll now want to move that commit to a different branch like 'feature/contact'. For that let's run the command 

```git
git checkout feature/contact
```

Now we're in the contact branch and if we inspect the log, we'll see that the commit is now in both branches and what's left is to remove it from the first branch.

So now let's go back to the previous branch (with `git checkout -` remember?) and we'll take the id of the commit that's before the one we want to remove and run the command 

```git
git reset --hard {commitId}
```

We'll get a message from Git saying that 'HEAD is now at {previousCommitId} {previousCommitName}'. 

So essentially the HEAD pointer moved back one commit and it's like that latest commit was never created in the first place, but it still exists in the branch that we want it to be.

Another option to do it is to use the `git cherry-pick` command.

For instance, if we're in the 'feature/about' branch, make note of the commit id (the one we want to copy) and then move to the wanted branch and run the command 

```git
git cherry-pick {commitId}
```

Now the changes of the commit from the other branch will be applied to the branch that we're on. 

Note that cherry-pick applies the changes of the selected commit by creating a _new_ commit on the branch instead of copying the entire commit. 

We'll now have to go back to the other branch and remove the commit from there like we did before.

Also note that `git cherry-pick` works if we want to take _one_ commit from a branch and copy the changes into another branch whereas with `git checkout` we're taking all the recent commits and moving them to the other branch.

With that, we have moved a commit to it's corresponding branch _before_ pushing to the remote which makes things easier to deal with locally. 

## Getting into more advanced stuff 

We'll now be looking into how to handle commits across different branches and remotes with some of the extra firepower that Git gives us. 

But you know what? I just looked through the whole article and realized that's it's getting quite long and unwieldy.

So I'll be saving the advanced stuff for a Git tricks part 2. 

In that one we'll be looking at things like...

- The different options that `git reset` has. 
- How to recover commits that may seem lost with `git reflog`.
- Doing forced pushes with caution using `--force-with-lease` instead of `--force`. 
- And how to manage changes, commit messages and more with `git rebase`. 

---

So, there you have it, some extra tricks that your probably didn't know when using Git for the traditional software development workflow. 

I hope this has been useful, I know a couple of years back I'd be using Git without understanding most of its power and just limiting myself to the most used commands and nothing more.

And now that was it for this week's post!

![Tom Hanks waving](https://media.giphy.com/media/AhJIPUnoUYgyA/giphy.gif)

T Hanks for reading so far and I hope to see you the next week for part 2!