4 Useful Solutions to Common Git Problems
Tags: git, productivity, tutorial
Published: 2019-08-26 22:45:50

<sup>Cover Image: [Black and Silver Laptop Computer on Round Brown Wooden Table](https://www.pexels.com/photo/black-and-silver-laptop-computer-on-round-brown-wooden-table-1181243/) by [Christina Morillo](https://www.pexels.com/@divinetechygirl)</sup>
These days, most developers are using some form of version control, and the most popular version control system used today is git.

I've written a few handy git articles:
- [10 Git Tricks to Save Your Time and Sanity](https://dev.to/jacobherrington/10-git-tricks-to-save-your-time-and-sanity-289h)
- [Git Bisect is Easy](https://dev.to/jacobherrington/git-bisect-is-easy-44ol)
- [A Quick Guide to Hunky Git](https://dev.to/jacobherrington/a-quick-guide-to-hunky-git-49no)
- [10 More Git Tricks That You Should Know](https://dev.to/jacobherrington/10-more-git-tricks-that-you-should-know-3bbp)

This one will be a continuation of those articles, with more focus on pragmatism. In the previous articles, I was sharing interesting things that you could do with git. In this article, I'm going to focus on things that every developer should know how to do.

### 1. Add a change to the last commit

Modifying the last commit is handy for anyone who has forgotten to stage a change (which is everyone who has ever used git).

This is really simple. All you have to do is stage the file you forgot to stage and then use the `git commit --amend` command.

Say I forgot to stage my changes to the README file, this is what I'd do:

```sh
git add README.md
git commit --amend
```

I'd be prompted to modify the commit message and then: Tada! The README.md changes have been added to the last commit.

### 2. Split the last commit into multiple commits

Say you have a different problem. If you accidentally staged something and then made a commit when you intended to make two commits.

All you need to do is walk back by one commit using the `git reset` command:

```sh
git reset HEAD~1
```

Then use `git add` to stage your changes (I recommend using `git add --patch`, [I wrote an article on it, if you're not familiar](https://dev.to/jacobherrington/a-quick-guide-to-hunky-git-49no)), and commit:

```sh
git add --patch
git commit -m "This is the first commit"
```

Then repeat the process as many times as needed:

```sh
git add --patch
git commit -m "This is the second commit"
```

One commit has become many. 💥

### 3. Squash some previous commits into one commit

Every developer should know how to squash commits. This is something you will probably be asked to do if you make a contribution to Open Source and you've made a few redundant or poorly-worded commit messages.

I'm going to share a couple of approaches, one that uses `git rebase`, and one that doesn't.

Without `git rebase`, you can easily squash the last few commits into one. First, you'll want to use the `git reset` command to move back through the commits you'd like to squash.

You can do this by passing `HEAD~x` to the `git rebase` command, where `x` is the number of commits you'd like to squash together.

For example, if you want to squash the previous three commits into one commit, you'd run the following command:

```sh
git reset HEAD~3
```

If you were to check the log, you'd notice that you are now three commits behind your previous position.

A quick `git log` will reveal that all of the changes from the previous three commits still exist on your machine, but are now unstaged.

To squash them together into one commit, all you need to do is stage them and commit them:

```sh
git commit -am "Some commit message"
```

Congratulations! 🎉 You've squashed three commits into one!

Alternatively, you can use `git rebase` with the interactive flag. That would look something like this:

```sh
git rebase -i master
```

Replace master with the branch where you will eventually merge.

`git rebase -i` will drop you into a text editor that looks something like this:

```
pick 1eabc17a8 Add data-attributes to container elements
pick 90c58b487 Fix react-dom warning

Rebase 5f5e140ea..90c58b487 onto 5f5e140ea (2 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
```

Now, this can be a little intimidating if you've never performed a rebase before, but it's actually very simple.

To squash these two commits, simply replace the word `pick` on the second line with `squash`:

```
pick 1eabc17a8 Add data-attributes for styling checkout
squash 90c58b487 Fix react-dom warning; non-critical, but annoying
```
Save the file (if you're in Vim, this is done with `:wq`), and you'll be dropped into a text editor to write a commit message. When you're happy, save the commit and you're done!

Woohoo! 🤠 Now you've seen two different ways to squash commits.

You might be wondering why you'd choose to use `rebase` when the first method was so easy, that's understandable. Using `git rebase` gives you a lot more control over big changes, and I recommend getting comfortable with it for those problems.

### 4. Get the most recent changes from another branch

When you work with feature branches, this is something you might be doing multiple times a day!

There are two ways to do this too.

The most common method for doing this is the `git merge` command. All you have to do with run the `git merge` command with the name of the branch you'd like to pull in changes from. For example, if you're getting the most recent changes from master:

```sh
git merge master
```

This creates a new commit, which is referred to as a merge commit. A merge commit is basically just an indication that a merge happened, and there is nothing wrong with having these commits in your git history (in my opinion).

However, some people dislike the presence of merge commits in their repository's history. For those people, you can use `git rebase` to catch up with another branch. This is typically how I like to get my feature branches caught up with master:

```sh
git rebase master
```

As long as nothing funky has happened, this will painlessly replay your changes on top of the master branch, catching you up without creating a merge commit.

🤗

### There's more...

I'm writing [a lot of articles](https://jh.codes) these days, I run a [podcast](https://www.devpath.fm), and I've started sending out a [newsletter digest](https://pages.convertkit.com/674caf55d4/f30f7753a7) about all of the awesome stories I'm hearing.

You can also follow me on [Twitter](https://twitter.com/jakeherrington), where I make silly memes and talk about being a developer.