5.4 KiB
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
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:
# 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
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
# 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
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
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:
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 --forcerewrites remote history. Fine on your own private repos, destructive in shared ones. Use--force-with-leaseas 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 statusandgit log --onelineare always your first move. Understand the state before doing anything.