git.md
# Git
Day-to-day commands plus the intermediate moves: rebase, reset, stash, reflog.

## Configuration
One-time identity, plus aliases that pay for themselves. `--global` writes to
~/.gitconfig; omit it for repo-local settings.
```bash
git config --global user.name "Anguished Turtle"
git config --global user.email you@example.com
git config --global init.defaultBranch main
git config --global pull.rebase true        # rebase, don't merge, on pull
git config --global alias.lg "log --oneline --graph --decorate --all"
```

## Branching & merging
Modern Git uses `switch` / `restore` instead of the overloaded `checkout`.
```bash
git switch -c feature/login     # create and switch (= checkout -b)
git switch main                 # move back
git branch -d feature/login     # delete a merged branch (-D forces)
git merge feature/login         # fast-forward when possible
git merge --no-ff feature/login # always record a merge commit
```
A *fast-forward* just advances the branch pointer; `--no-ff` keeps an explicit
merge commit so the feature's history stays grouped.

## Staging & committing
```bash
git add -p                      # stage hunk-by-hunk, interactively
git commit -m "Add login form"
git commit --amend              # rewrite the last commit
git commit --fixup <sha>        # queue a fix to autosquash later
git restore --staged file.txt   # unstage but keep the edit
```
> Tip: `git add -p` is the fastest way to split messy work into clean,
> reviewable commits: accept (y), skip (n), or split (s) each hunk.

## Rebasing & rewriting history
```bash
git rebase main                 # replay your branch on top of main
git rebase -i HEAD~5            # squash / reorder / edit the last 5
git rebase --autosquash -i main # fold fixup! commits in automatically
git rebase --abort             # bail out, restore pre-rebase state
```
> Golden rule: never rebase commits you've already pushed and shared, since it
> rewrites their SHAs and forces everyone else to reconcile.

## Undoing things
Pick by what you want to keep:
| Goal                                    | Command                     |
| --------------------------------------- | --------------------------- |
| Discard a working-tree change           | `git restore file`          |
| Unstage, keep the change                | `git restore --staged file` |
| Undo last commit, keep changes staged   | `git reset --soft HEAD~1`   |
| Undo last commit, keep changes unstaged | `git reset HEAD~1`          |
| Throw away the commit and the changes   | `git reset --hard HEAD~1`   |
| New commit that inverts an old one      | `git revert <sha>`         |
> Safety net: `git reflog` lists every position HEAD has held, so
> `git reset --hard <sha>` can recover a "deleted" commit.

## Stashing & inspecting
```bash
git stash push -m "wip: half-done refactor"
git stash list
git stash pop                   # reapply and drop the latest stash
git log --oneline --graph --all
git diff main...feature         # what feature added since it forked
git blame -L 10,20 app.py       # who last touched lines 10-20
git bisect start                # binary-search history for a bad commit
```

© 2026 anguishedturtle.com