Add git reference guide and update README

This commit is contained in:
Einar 2026-05-09 23:43:17 +02:00
parent 49fa44fe8d
commit 89748bffe2
2 changed files with 174 additions and 2 deletions

View file

@ -4,5 +4,5 @@ Personal reference docs for tools I use regularly.
## Tools
- [rclone](rclone.md) — File syncing and copying between local storage and
remote destinations. SFTP, object storage, and 60+ backends.
- [git](git.md) — Version control. Tracking changes, committing, pushing to Forgejo, undoing mistakes.
- [rclone](rclone.md) — File syncing and copying between local storage and remote destinations. SFTP, object storage, and 60+ backends.

172
git.md Normal file
View file

@ -0,0 +1,172 @@
# git
## What is it
git is a distributed version control system. It tracks changes to files over
time, lets you move between states (commits), and makes it safe to experiment
because nothing is ever truly lost.
The mental model that makes everything click: git is a timeline of snapshots.
Each commit is a complete snapshot of your project at a point in time, with a
pointer to the commit before it. That's it. Branches are just named pointers
to commits. Everything else follows from this.
## What it is mainly used for
- Tracking changes to files over time with a full history
- Safely experimenting — you can always go back
- Pushing code or content to a remote (like Forgejo) for safekeeping
- Collaborating with others (or your future self) on the same codebase
## Core concepts
**Repository (repo)** — a folder that git is tracking. The `.git/` directory
inside it holds the entire history. Don't touch `.git/` directly.
**Commit** — a snapshot of your files at a point in time. Every commit has
a unique hash (e.g. `f649b2b`) and a message describing what changed.
**Branch** — a named pointer to a commit. `main` is the default branch.
Creating a branch lets you work on something without touching `main`.
**Remote** — a copy of the repo somewhere else. In your case, Forgejo.
Conventionally named `origin`.
**Staging area** — a holding area between your working files and a commit.
You explicitly choose what goes into each commit using `git add`.
## Setting up a new repo
```bash
cd ~/my-project
git init
git add .
git commit -m "Initial commit"
git remote add origin git@vps-forgejo-01.warthog-rockhopper.ts.net:egeidal/my-project.git
git push -u origin main
```
The `-u` flag sets `origin/main` as the upstream — after this, a plain
`git push` is enough.
## Daily workflow
The loop you'll use constantly:
```bash
# 1. Check what has changed
git status
# 2. Stage the files you want to commit
git add filename.md # specific file
git add . # everything changed
# 3. Commit with a message
git commit -m "Add rclone SSH key section"
# 4. Push to Forgejo
git push
```
## Useful commands
### Seeing what's going on
```bash
git status # what's changed, what's staged
git log # full commit history
git log --oneline # compact one-line history
git diff # unstaged changes
git diff --staged # staged changes (what will be committed)
```
### Undoing things
```bash
# Unstage a file (undo git add, keep the changes)
git restore --staged filename.md
# Discard changes to a file entirely (cannot be undone)
git restore filename.md
# Amend the last commit (message or content)
git commit --amend --no-edit # keep message, update content
git commit --amend -m "Better message" # change message
# Undo the last commit, keep the changes staged
git reset --soft HEAD~1
# Undo the last commit, keep the changes unstaged
git reset HEAD~1
```
### Working with remotes
```bash
git remote -v # show configured remotes
git remote add origin <url> # add a remote
git push # push current branch
git push -u origin main # push and set upstream
git pull # fetch + merge from remote
git fetch # fetch without merging
git clone <url> # clone a remote repo locally
```
### Branches
```bash
git branch # list branches
git branch my-feature # create a branch
git switch my-feature # switch to a branch
git switch -c my-feature # create and switch in one step
git merge my-feature # merge branch into current branch
git branch -d my-feature # delete a branch
```
## .gitignore
A `.gitignore` file tells git which files to never track. Put it in the root
of your repo.
```
# Example .gitignore
.DS_Store
*.log
secrets.env
node_modules/
```
Files already tracked by git won't be ignored just by adding them here — you
need to untrack them first:
```bash
git rm --cached filename
```
## Useful flags
| Flag | What it does |
|------|-------------|
| `--oneline` | Compact log output — one commit per line |
| `--all` | Show all branches in log |
| `--graph` | Show branch/merge history as ASCII graph |
| `--soft` | Reset keeping changes staged |
| `--amend` | Modify the last commit |
| `--no-edit` | Keep the existing commit message when amending |
| `-u` | Set upstream remote when pushing |
| `-v` | Verbose — show more detail (e.g. with `git remote -v`) |
| `--cached` | Apply command to staging area only |
| `--force` | Force push — overwrites remote history. Use with care |
## Notes
- `git push --force` rewrites remote history. Fine on your own private repos,
destructive in shared ones. Use `--force-with-lease` as a safer alternative.
- Commit messages are for your future self. "Fix stuff" is useless in six
months. "Fix rclone SSH key format in guide" is not.
- Commit early and often. Small commits are easier to understand and undo
than one giant commit with everything in it.
- The staging area feels annoying at first but is actually useful — it lets
you make two unrelated changes and commit them separately with clear messages.
- If something goes wrong, `git status` and `git log --oneline` are always
your first move. Understand the state before doing anything.