Git: Learn Interactive Commands
Tags: git
Published: 2021-09-15 13:50:26

You probably started out using Git in the command line. That's great! But unfortunately it's common, and understandable, for people to then move straight to a GUI version of Git, such as one of the many VSCode Git extensions.

I did something similar when I first started collaborating with Git, but if I had just stuck it out with the command line I would've learned much more rapidly.

## Why Use Command Line?
###### _First Principles_

Okay, I'm not saying Git GUIs are bad, they're the opposite in fact. I use them all the time nowadays for certain tasks, mainly visualising complex tree structures.

What I am saying is, _**if**_ you're wanting to get the most out of Git and fully understand it, you should learn it through the command line first.


### Interactive Add
###### _Clean Up Your Commits_

This is really useful when I've been writing a feature and I've maybe also updated other things along the way that I don't want to include in the same commit e.g. fixing tests, refactoring other classes etc.

This allows you to see the state of all changes and provides all the options you can use.

```bash
$ git add -i
           staged     unstaged path
  1:    unchanged        +2/-0 README.md

*** Commands ***
  1: status	  2: update	  3: revert	  4: add untracked
  5: patch	  6: diff	  7: quit	  8: help
What now> 
```

We can then selectively stage specific files using the add or patch option options.

The add option stages all changes in the file, the patch option goes through all the different hunks (changes grouped together) within the file and allows you to optionally stage each hunk.

```bash
           staged     unstaged path
  1:    unchanged        +2/-0 README.md
Patch update>> 1
           staged     unstaged path
* 1:    unchanged        +2/-0 README.md
Patch update>> 
diff --git a/README.md b/README.md
index 48bee75..6056e4a 100644
--- a/README.md
+++ b/README.md
@@ -20,3 +20,5 @@ $ login --store=https://dev-mimir.com
 $ populate products
 $ node serve
+
+some change
(1/1) Stage this hunk [y,n,q,a,d,e,?]?
```

---

### Interactive Rebase
###### _Clean Up Your Branch_

Okay this is my favourite Git command, it's saved my bacon more times than I can remember now. When in doubt, interactive rebase. 

So when I'm working on my local branch I tend to make a lot of messy commits, sometimes they'll be in an order that don't really make sense that might cause issues down the line if we ever want to rollback, they include things that they really shouldn't, they're poorly described etc.

Before I push up to my remote branch I usually have to do an interactive rebase to clean up my branch. 

```bash
$ git rebase -i HEAD~4
 pick a204433 refactor: rename TicketBoard
 pick 72ceae8 refactor: generic support tickets table
 pick ba2925d refactor: organise React folder components/services
 pick 95023db feat(wip): added TicketBoard placeholder services
 
 # Rebase 9c24617..95023db onto 95023db (4 commands)
 #
 # Commands:
 # p, pick <commit> = use commit
 # r, reword <commit> = use commit, but edit the commit message
 # e, edit <commit> = use commit, but stop for amending
 # s, squash <commit> = use commit, but meld into previous commit
 # f, fixup <commit> = like "squash", but discard this commit's log message
 # x, exec <command> = run command (the rest of the line) using shell
 # b, break = stop here (continue rebase later with 'git rebase --continue')
 # d, drop <commit> = remove commit
 # l, label <label> = label current HEAD with a name
 # t, reset <label> = reset HEAD to a label
 # m, merge [-C <commit> | -c <commit>] <label> [# <oneline>]
 # .       create a merge commit using the original merge commit's
 # .       message (or the oneline, if no original merge commit was
 # .       specified). Use -c <commit> to reword the commit message.
 #
 # These lines can be re-ordered; they are executed from top to bottom.
 #
 # If you remove a line here THAT COMMIT WILL BE LOST.
 #
 # However, if you remove everything, the rebase will be aborted.
 #
 # Note that empty commits are commented out
```

Look at all the helpful documentation that you're given with this command, you practically don't even need to remember what anything does because it's all right there. 

So, if I wanted to squash the first and last two commits together, that's easy to do. I just need to follow the docs and re-order the commits and change from `pick` to `squash`

```bash
$ git rebase -i HEAD~4
 pick ba2925d refactor: organise React folder components/services
 pick 95023db feat(wip): added TicketBoard placeholder services
 squash a204433 refactor: rename TicketBoard
 squash 72ceae8 refactor: generic support tickets table
```

---

## Conclusion 

I hope this post has highlighted that you don't need much to get a lot out of Git. Just these few commands can give you a lot of flexibility and control, which is often something that I find lacking in some Git GUIs.