---
title: 'Key notes while working with git'
date: '2021-08-12'
tags: ['git', 'git-notes', 'git-alias', 'git-workflows']
summary: 'Key notes to save plenty of time while working with git for command-line-developer'
images:
  [
    '/static/images/banners/a-close-up-of-a-text-description-on-a-computer-screen__yancymin__842ofHC6MaI.jpeg',
  ]
authors: ['default']
---

This post is written for developers who prefer working with `git` via `command-line` like me. If you love GUI, hope you still can find something useful here <Twemoji emoji="beaming-face-with-smiling-eyes" />

## Git alias

> Git aliases are a powerful workflow tool that create shortcuts to frequently used Git commands

`git alias` in the simpleset term is creating a _shortcut_ (short `command`) for the long ones, make them easier to remember and you can type it faster.

### Syntax

```bash
git config --global alias.<shortcut> <original-command>
```

<Twemoji emoji="warning" /> Use `--global` flag to tell **git** that the alias will be used in all
projects (otherwise, it will only work on your current working project!)

<Twemoji emoji="warning" /> Use quotes (`''`) if the `original-command` includes space(s).

For me, I create aliases for almost all commands that I work with daily.

<Twemoji emoji="keycap-1" /> **Git status**

Check the changes before committing:

```bash
git config --global alias.st status
```

```bash showLineNumbers
# Now instead of `git status`, use `git st`
git st
On branch v2
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
        modified:   components/ui/twemoji
        modified:   css/tailwind.css
        modified:   data/blog/git-notes.mdx

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

> Tip: Use `git st` with `--short` flag or `-s` to see the short-format of the changes, and... you know it - create an alias for this command too

```bash
git config --global alias.s 'status --short'
```

```bash showLineNumbers
# Now instead of `git st`, use `git s`
git s
  M components/Image.js
  M data/blog/git-notes.mdx
  ?? public/static/images/force-with-lease.jpg
```

Much clearer results and much faster typing, right? <Twemoji emoji="beaming-face-with-smiling-eyes" />

<Twemoji emoji="keycap-2" /> **Git commit**

```bash
git config --global alias.cm 'commit -m'
```

Commit changes (`add/stage` changes before):

```bash
git cm "Initial commit"
```

> [!TIP]
> If the changes are only for existing files (neither new file nor deleted file), use `--all` or `-a` flag so you don't have to add or stage changes before committing

```bash
git config --global alias.cam 'commit -am'
```

```bash showLineNumbers
# Now instead of 2 git commands
git add style.css # `style.css` is already existed, not new file!
git cm "Update style"

# Use only 1 command
git cam "Update style"
```

<Twemoji emoji="keycap-3" /> **Git stash**

> Stash the changes in a dirty working directory away <Twemoji emoji="grinning-face-with-sweat" />

Like the definition, use `git stash` when you need to **"stash"** the changes before pulling new stuff from remote repo:

```bash
# Too short to create an alias
git stash
```

Applying the stashed changes after pulling:

```bash
git stash pop
```

Create an alias for it:

```bash showLineNumbers
git config --global alias.sp 'stash pop'

# Now
git sp

# Is equal
git stash pop
```

<Twemoji emoji="keycap-4" /> **Git `pull/push`**

Always [`pull rebase`](https://www.atlassian.com/git/tutorials/merging-vs-rebasing) and `force push` to have a clean commit tree!

- `pull rebase`

  ```bash
  git config --global alias.prb 'pull origin --rebase'
  ```

  ```bash showLineNumbers
  # Now
  git pull origin --rebase main

  # Is equal
  git prb main
  # Or
  git prb master
  ```

- What if a conflict occurs after rebasing?

  List all the conflicts with `git diff` and create an alias for this command:

  ```bash
  git config --global alias.cf 'diff --name-only --diff-filter=U'
  ```

  ```bash showLineNumbers
  # List all the conflicts
  git cf

  # Reolve all conflict then stage changes
  git add .

  # Finish rebasing
  git rebase --continue
  ```

- `force push`

  When you finish resolving the conflicts that occured after rebasing, we need to **force** push the changes to the remote repo:

  ```bash showLineNumbers
  git config --global alias.pf 'push --force-with-lease'

  # Now after rebasing
  git pf
  ```

  [Why not `--force`?](https://git-scm.com/docs/git-push#Documentation/git-push.txt---force-with-leaseltrefnamegt)

  **TL;DR**

  > The `--force` flag will make git overwrite the remote repo with local changes without comparing with possible updates in the remote after rebasing, which can be dangerous if 2 developers working on the same branch. <br/> `--force-with-lease` in the opposite way, make sure you can push only when no updates on the upstream exist.

  ![force-with-lease](/static/images/force-with-lease.jpg)

<Twemoji emoji="keycap-5" /> **Git checkout**

```bash showLineNumbers
git config --global alias.co 'checkout'

# Eg
git co main
```

Create a new branch:

```bash showLineNumbers
git config --global alias.cob 'checkout -b'

# Eg
git cob feature-x
```

> [!TIP]
> Use `git co -` to checkout to the previous branch.

Example:

```bash {3} showLineNumbers
git branch
dev
* feature-x-y-z__ISSUE_ID
main
# The current branch is `feature-x-y-z__ISSUE_ID`

# Checkout to `dev`
git co dev
# Do something
# Commit ...

# Now to come back to `feature-x-y-z__ISSUE_ID` use
git co -
# Instead of
git checkout feature-x-y-z__ISSUE_ID
```

<Twemoji emoji="keycap-6" /> **Git diff**

Check the changes before commit (Usually, I use this to make sure no `debug`, `hardcode` or `console.log` is left in my code).

```bash showLineNumbers
git config --global alias.d 'diff'

# Eg
git d style.css
```

### Note

All your aliases can be found in `~/.gitconfig` file (MacOS). You can open this file directly and edit any alias you want.

```bash
vim ~/.gitconfig
```

```bash:.gitconfig showLineNumbers
# Find the alias part in the config file
[alias]
  s = status --short
  st = status
  cm = commit -m
  # ...
```

Prerequisite to be able to edit this file: knowing [`vim`](https://github.com/vim/vim) <Twemoji emoji="face-with-tears-of-joy" />

![vim-meme](/static/images/vim-meme-exit.png)

## Git workflow

My daily workflow working with `git` (all aliases explained in the [above section](#git-alias))

```bash {5,14,26,36} showLineNumbers
# Stash changes
git stash

# Update changes from upstream
git prb main

# Apply stash changes
git sp

# Resolve conflict if existed
# Work

# Check working status
git s

# Check file changes (if needed)
git d # or git d file.ext

# Stage changes
git add .

# Commit
git cm "commit message"

# Or skip stage changes if no new file created/deleted
git cam "commit message"

# Update changes again
git prb main

# If there're conflicts, resolve all then
git add file.ext
git rebase --continue

# Force push
git pf

# Making pull request
```

Here is my entire workflow but only the highlighted commands are the most commonly used <Twemoji emoji="beaming-face-with-smiling-eyes" />

## `.gitignore` and `.gitkeep`

<Twemoji emoji="keycap-1" /> **.gitignore**

[Useful ready to use templates](https://github.com/github/gitignore)

Tip: ignore all files inside a directory but keep 1 specific file

```bash {5} showLineNumbers
# Ignore all file in a directory
homework/*

# Keep only this file
!homework/file-to-keep
```

<Twemoji emoji="keycap-2" /> **.gitkeep**

How to push an empty directory to the remote repo?

> Create a `.gitkeep` file, put it in the empty directory, then you can push the directory to the upstream!

This it not an [official feature](https://git-scm.com/search/results?search=.%20gitkeep) of `git` itself! Just a convention of some random dev out there <Twemoji emoji="beaming-face-with-smiling-eyes" />.

**Explannation:** the trick here is to make the directory non-empty (it has a file inside!). So, we can push it to the upstream. Thus, `.gitkeep` could be any file that you think about (empty or not doesn't matter). Choose `.gitkeep` causes it easy to understand and remember.

## Wrapping up

Those are all my notes while working with `git`, how I understand the concepts and how I work with it faster. Would love to see your use cases in the comment section!

Happy sharing <Twemoji emoji="clinking-beer-mugs" />

## References

- [Git Alias Overview](https://www.atlassian.com/git/tutorials/git-alias)
- [Merging vs. Rebasing](https://www.atlassian.com/git/tutorials/merging-vs-rebasing)
- [Git docs: --force-with-lease](https://git-scm.com/docs/git-push#Documentation/git-push.txt---force-with-leaseltrefnamegt)
