Concepts #
- Three stages of a file: working directory (in-progress edits) → staging area (ready to commit) →
.gitrepository (committed/saved locally). Almost every command below moves a file between these three places. .gitignoreonly stops untracked files from being added — a file already committed stays tracked even after you add it to.gitignore. Untrack it withgit rm --cached <file>first. Sample.gitignorefiles.checkoutvs.switch/restore:git checkoutis the old do-everything command (switch branches, restore files, view old commits). Modern Git split it intogit switch(branches) andgit restore(files) becausecheckout’s dual role was a common source of mistakes. Both forms are shown below —checkoutbecause it’s what the source tutorials use and still works everywhere,switch/restorebecause they’re clearer for new scripts/habits.
Basic Setup & Navigation #
git --version— check which Git version is installed.git init— turn the current directory into a Git repo by creating a.gitfolder (delete that folder to un-git a project).git clone <url>— copy a remote repo, and its full history, to a new local directory.git config --list— show current configuration settings.--local— current repo only ·--global— all your repos ·--system— every user on the machinegit config --global <setting> <value>— change a setting, e.g.git config --global user.name "Your Name"git config alias.st status— create a shortcut (git stnow runsgit status)man git-config— full list of every config option
git help <verb>orgit <verb> --help— open the manual page for a command.
Prepare to Commit (Staging) #
git status(or-s/-sbfor a short form) — see what’s changed, staged, or untracked.git add <file>— stage a new/modified file (re-run after further edits to re-stage the latest version).git add -A/--all— stage everything (new, modified, deleted) in the whole working tree; the default for plaingit add .at the repo root.git add -u/--update— stage only changes to files Git already tracks, not new files.git add .— like-Abut limited to the current directory and below.git add -p— interactively choose which chunks of a changed file to stage, instead of the whole file.git mv <old> <new>— rename/move a tracked file (equivalent tomv+git add+git rm).git rm <file>— delete a file from both the working directory and the repo.git rm --cached <file>— stop tracking a file but keep it on disk (typical fix when a file was committed before being added to.gitignore).git reset <file>(orgit reset HEAD <file>) — unstage one file, keeping its edits.git reset— unstage everything, keeping edits.
Make Commits #
git commit— commit staged changes, opening your editor for the message.git commit -m "message"— commit staged changes with an inline message.git commit -a -m "message"/git commit -am "message"— stage every tracked file’s changes and commit in one step (does not pick up brand-new untracked files).git commit --amend -m "New message"— replace the last commit’s message. ⚠️ Rewrites that commit’s hash.git commit --amend(message unchanged in editor) — add a staged file to the previous commit instead of the message. ⚠️ Also rewrites the hash.
Move Between Branches #
git switch <name>orgit checkout <name>— switch to an existing branch.git switch -c <name>orgit checkout -b <name>— create a new branch and switch to it in one step.git branch <name>— create a branch without switching to it.git branch— list local branches.git branch -a— list local and remote-tracking branches.git branch --sort=-committerdate— list branches ordered by most recently committed to (handy for finding your recent work).git branch --merged— list branches already fully merged into the current one (safe to delete).git branch -d <name>— delete a local branch (Git refuses if it isn’t merged yet).git branch -D <name>— force-delete a branch even if unmerged.git push origin --delete <name>— delete the branch on the remote too.
Diffing #
git diff— unstaged changes vs. the staging area.git diff --staged— staged changes vs. the last commit.git diff --staged --no-renames— same, without Git’s rename detection.git diff HEAD— all staged + unstaged changes vs. the last commit, combined.git diff -r HEAD/HEAD~1/HEAD~2— unstaged changes vs. a specific past commit.git diff <commit> <commit>— changes between any two commits (e.g.git diff HEAD~2 HEAD~3).git diff <commit> <file>— changes to one file since a given commit.git diff <commit> --stat/git show <commit> --stat— a summary (file names + line counts) instead of a full diff.git diff --stat --cached origin/main— summary of what’s staged, compared against the remote.git show <commit>— full diff between a commit and its parent.git show <commit> <filename>— a single file’s changes at that commit.git annotate <file>/git blame <file>— show which commit (and author) last changed each line of a file.
Ways to refer to a commit #
Anywhere <commit> is used above, you can pass:
| Form | Example | Meaning |
|---|---|---|
| Branch name | main |
tip of that branch |
| Tag | v0.1 |
a named, usually release, point |
| Commit ID | 3e887ab |
short or full SHA1 hash |
| Remote branch | origin/main |
tip of a branch on a remote |
| Current commit | HEAD |
where you currently are |
| N commits back | HEAD~3 or HEAD^^^ |
3 commits before HEAD |
Log & Code Archaeology #
git log— full history, reverse-chronological.git log -1— just the most recent commit, full SHA1.git log --oneline— one line per commit, short SHA1 (add-n 10to limit the count).git log --stat— commits plus which files each one touched.git log --patch— commits plus each one’s full diff.git log --graph main— draw the branch/merge structure as ASCII art.git log <file>— every commit that touched a specific file.git log --follow <file>— same, but keeps tracking history across renames.git log -G banana— find every commit that added or removed the text “banana” (a code-search tool, useful for tracking down when a line was introduced or deleted).git reflog— history of everywhereHEADhas pointed (branch switches, resets, commits, rebases). Your safety net for “lost” commits.
Discard / Undo Changes #
git checkout -- <file>orgit restore <file>— discard unstaged changes, restoring the last committed version.git checkout HEAD <file>orgit restore --staged --worktree <file>— discard both staged and unstaged changes to one file.git reset --hard— discard all staged and unstaged changes in the whole repo. ⚠️ Unrecoverable for those edits.git reset --hard <hash>— same, but also rewinds the branch to<hash>, discarding later commits’ changes too.git clean -df— delete untracked (d)irectories and (f)iles (thingsgit statusshows as “untracked”).git stash— shelve staged + unstaged changes for later without committing them.
Edit History #
⚠️ Everything in this section rewrites commit hashes. Safe only on commits/branches you haven’t shared with anyone yet.
git reset HEAD~1— “undo” the most recent commit, keeping its changes in your working directory (mixed reset, the default).git reset --soft <hash>— rewind to<hash>, keeping later changes staged.git reset --mixed <hash>(same as plaingit reset <hash>) — rewind to<hash>, keeping later changes unstaged in the working directory.git rebase -i HEAD~5— interactively edit the last 5 commits: reorder, reword, orfixup/squashthem into fewer commits.git commit --amend— change the last commit’s message, or add a forgotten staged file to it.- Undo a failed rebase:
git reflog <branch>to find the commit ID from before the rebase, thengit reset --hard <commit>to jump back to it. git revert <hash>— create a new commit that undoes a prior one, leaving history intact. The safe way to undo something that’s already been pushed/shared.git cherry-pick <hash>— copy one commit’s changes onto the current branch (leaves the original commit where it was).
Combine Diverged Branches #
- Merge —
git switch mainthengit merge <branch>: brings another branch’s commits into the current one via a new merge commit. Preserves both branches’ history as-is. - Fast-forward merge — same commands, but if
mainhas no new commits since<branch>diverged, Git just moves themainpointer forward (no merge commit created). - Rebase —
git switch <branch>thengit rebase main: replays<branch>’s commits on top ofmain, producing a linear history instead of a merge commit. ⚠️ Rewrites the rebased branch’s commit hashes. - Squash merge —
git switch mainthengit merge --squash <branch>thengit commit: combines all of<branch>’s commits into a single new commit onmain.
Restore an Old File #
git checkout <commit> <file>orgit restore <file> --source <commit>— pull one file’s contents from an older commit into your working directory, without touching anything else.
Remotes #
git remote add <name> <url>— register a remote repository under a short name (usuallyorigin).git remote -v— list configured remotes and their URLs.
Push Your Changes #
git push origin main— push themainbranch to theoriginremote.git push— push the current branch to its already-configured remote “tracking branch”.git push -u origin <name>— push a branch for the first time and set up tracking so plaingit push/git pullworks afterward (-u=--set-upstream).git push --force-with-lease— force-push, but abort if the remote has commits you haven’t seen yet (safer than plain--forcefor shared branches).git push --tags— push tags along with commits.
Pull Changes #
git fetch origin main— download remote changes without touching any of your local branches.git fetch <branch1> <branch2>— fetch one branch’s commits into another.git pull origin main/git pull— fetch and merge remote changes into your current branch.git pull --rebase— fetch, then rebase your current branch on top of the fetched changes instead of merging (keeps history linear).
Stashing #
git stash/git stash save "<comment>"— shelve working-dir + staged changes onto a stack.git stash list— list all stashes (stash@{0},stash@{1}, …).git stash show— summarize the diff in a stash.git stash pop— reapply the most recent stash and remove it from the stack.git stash apply stash@{0}— reapply a stash but keep it on the stack.git stash branch <name>— apply a stash onto a brand-new branch and drop it from the stack (useful if applying to the current branch would conflict).git stash drop stash@{0}— delete one specific stash.git stash clear— delete every stash.- Tip: stash on one branch, then commit (or apply) on another — a quick way to move work-in-progress changes between branches.
Important Files #
.git/config— this repo’s local configuration (what--localreads/writes).~/.gitconfig— your global, per-user configuration (what--globalreads/writes)..gitignore— patterns for files Git should never track; generate examples at github.com/github/gitignore.
Diff/Merge GUI Tools #
Useful for resolving conflicts visually: DiffMerge, Sourcetree.
Resources #
Further reading at the git-scm.com/docs website and the Pro Git book.