5 scary Git commands you'll eventually have use for
Tags: beginners, git, webdev, productivity
Published: 2022-07-08 10:43:49

Version control is magical.

I strongly believe everyone should learn how to use it - not just developers. How many times did you complete homework back at school and create arrays of filenames to denote just how final that piece of work was?

Today, in modern web development, Git is an absolute pre-requisite. But it's still shocking to see just how many experienced developers are just scratching the surface of what Git can do for you.

In this blog post I hope to unearth at least one useful Git command you perhaps haven't come across or would even think to use.

## git rebase
Git rabasing is boils down to moving or combining a sequence of commits into a new base commit. It essentially appears like you've created your branch from a different commit base - extremely useful if you've been working on a branch for a while, you've diverged off of the main branch for a while and you run into conflicts when you try and merge back in.

It works something like this:

```bash
git checkout main # change to main branch
git pull origin main 
git checkout - # go back to last branch (feature branch)
git rebase main
# fix conflicts
git add .
git rebase --continue # until all changes are in
```

You can also use `--interactive` mode for rebasing which will let you manually select which commits you want to ignore throughout - helpful if you've made a commit purely to add some debugging and forgotten before committing. 

Now, some of you might be thinking you can just `git pull origin main` in your branch and resolve the merge conflicts _in an even easier fashion_. While they are both similar there's one massive difference that you want to keep in mind here:
* `git pull` will create a new commit that combines the two branches together
* `git rebase` will move the commits of one branch on top of the other

You can also use `git pull --rebase` to pull using rebase which can be great and save you a lot of time. However

`git rebase` will essentially keep your git history clean. 

**Why is this important?** 

It means you can safely and effectively use our next arcane power: `git bisect`.

## git bisect

`git bisect` uses binary search to find a commit that introduced some new unwanted functionality (read: bug). 

It kind of works like this:

Imagine you're digging for the commit that broke a feature that we knew was working in commit `0cd429f02` (or a tagged commit), and somewhere along the way we broke something and a test is failing. 

We can use git bisect to narrow down the commits and help us identify the culprit like so:

```bash
git bisect start
git bisect bad
git bisect good 0cd429f02
```

**Note: You can use `git bisect reset` to jump out of this.**

Once you've specified a good and a bad commit, bisect will find a commit in the middle of that range, check it out and give you some information regarding how many possible steps are left to split through.

Now that you're in your checked out commit you should run your tests and assuming it works, you can inform bisect of that by typing `git bisect good`, or tell bisect that that particular version is failing with `git bisect bad`.

Repeat the above steps and eventually you'll run out of revisions to test - bisect will then spit out the description of the first bad commit with a nice little summary - and there's your buggy commit. ✨

## git stash
Stashing is used to take your uncommitted changes (including staged) and temporarily "stash" them away for later. 

Extremely useful when you're not quite ready to commit a change, but need to move to another branch for some reason - maybe there's a bug you need to investigate. 

You can stash your content like this:

```bash
git status

Changes not staged for commit:
	modified:   README.md
	modified:   mix.exs
	modified:   test/inspyre_web/live/story_live_test.exs

no changes added to commit (use "git add" and/or "git commit -a")

git stash

git status

On branch main
Your branch is up to date with 'origin/main'.
```

Like magic your changes are seemingly gone.. or are they?

If you run `git stash list` you'll see a log of previously stashed events alongside the branch you were operating on and the last commit in that log. 

Running `git stash apply` will take the last stashed set of changes and apply them to your current branch **but will not remove them from your stash list**. If you know you won't need them this one time stash you'll want to use `git stash pop` to apply the changes and pop them out of your stash list.

## git reset --soft HEAD^N
Have you ever accidentally thought you changed branch but really you were still in the last feature you were working on?

Have you committed multiple times?

**Whoops**. It's cool - we can fix that. 

Use `git reset --soft HEAD^N` where N is the number of commits you want to un-commit to bring them back to you. From here you can stash or move to another branch and commit them there.

**Be careful not to type `--hard` though. That'll trash unsaved changes for good.**

## git reflog
Gits secret weapon / time capsule. 

`git reflog` will give you a list of every single thing you've done in git across every single branch. 

If you've accidentally ended up in a state you weren't expecting to be in, deleted things, merged things accidentally or can't figure out what's happened, reach for `git reflog` (at least before you trash everything and re-clone your repo).

## git branch -M (BONUS)
This one is simple but effective - and one I know several devs resort to deleting and recreating a branch to solve!  🤯 

Renaming a branch!

Simply type `git branch -M <new_branch_name>` to set your new branch name for the branch your currently in.


That's all folks. 

Hopefully that was useful for some - subscribe to my [Substack](https://chrisgregori.substack.com/) for similar content and [follow me on Twitter](https://twitter.com/codestirring) for more git (and general programming) tips.