# 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
```