git init Create a new, empty Git repository in the current folder.
Example
git init my-project Forgetting to add a .gitignore before the first commit — you end up tracking node_modules or build artefacts. Create .gitignore first.
Every essential git command explained in one sentence — with examples, gotchas, and the English phrases you'll actually say in standups.
Last reviewed:
git init Create a new, empty Git repository in the current folder.
git init my-project Forgetting to add a .gitignore before the first commit — you end up tracking node_modules or build artefacts. Create .gitignore first.
git clone Download a remote repository and its full history to your machine.
git clone https://github.com/user/repo.git
git clone git@github.com:user/repo.git # SSH clone Cloning with HTTPS each time prompts for a password. Set up SSH keys or a Git credential helper once and use SSH clone URLs.
git status Show which files are modified, staged, or untracked.
git status
git status -s # short, compact output Running git status is always safe — it never changes anything. Make it a habit before every commit.
git add Stage file changes — mark them as ready to be committed.
git add index.ts # stage one file
git add src/ # stage entire folder
git add -p # stage chunks interactively git add . stages ALL changed files including things you didn't intend to commit. Use git add -p (patch) or name specific files to be intentional.
git commit Record staged changes as a new snapshot in history.
git commit -m "feat: add login validation"
git commit --amend # edit the last commit (before push) git commit -a -m "..." automatically stages all tracked files — but skips untracked new files. Don't use it blindly.
git push Upload local commits to the remote repository.
git push origin main
git push -u origin feature/auth # set upstream and push Never force-push to a shared branch (main/master). git push --force rewrites history and breaks everyone else's local copies.
git pull Fetch remote commits and merge them into the current branch.
git pull origin main
git pull --rebase origin main # rebase instead of merge git pull is shorthand for git fetch + git merge. On a feature branch, git pull --rebase keeps history linear and avoids noisy merge commits.
git fetch Download remote commits without applying them to your working branch.
git fetch origin
git fetch --prune # also delete remote-tracking refs for deleted branches Unlike git pull, fetch is always safe — it never changes your working directory. Use it to inspect remote changes before merging.
git branch List, create, or delete branches.
git branch # list local branches
git branch feature/auth # create a branch
git branch -d feature/auth # delete merged branch
git branch -D feature/auth # force-delete unmerged branch Deleting a local branch doesn't delete the remote branch. Use git push origin --delete feature/auth to remove it from the remote.
git switch Switch to a different branch (modern replacement for git checkout).
git switch main
git switch -c feature/dark-mode # create and switch git switch was introduced in Git 2.23. You'll still see git checkout used everywhere — they're equivalent for branch switching.
git checkout Switch branches or restore specific files from history (legacy command with multiple roles).
git checkout main
git checkout -b feature/auth # create and switch
git checkout -- src/file.ts # discard changes in a file git checkout does too many things. Git split it into git switch (branches) and git restore (files) in v2.23, but git checkout still works everywhere.
git merge Combine the history of another branch into the current branch, creating a merge commit.
git switch main
git merge feature/auth
git merge --no-ff feature/auth # always create a merge commit A merge preserves the full history of both branches. This is the safest approach for shared branches. The result is a merge commit that has two parents.
git rebase Rewrite your branch's commits as if they started from the tip of another branch — producing a linear history.
git switch feature/auth
git rebase main # rebase feature onto latest main
git rebase -i HEAD~3 # interactive: squash/edit last 3 commits Never rebase commits that have already been pushed to a shared remote branch. Rebase rewrites commit hashes — this breaks everyone who has the old commits.
git stash Temporarily shelve uncommitted changes so you can switch context.
git stash # stash changes
git stash push -m "wip: login" # stash with a label
git stash pop # apply most recent stash and remove it
git stash apply stash@{1} # apply specific stash, keep it
git stash list # see all stashes
git stash drop stash@{0} # delete a stash Stashes are local only — they're not pushed to remotes. A stash is a shortcut, not a backup. Don't accumulate many stashes; they're easy to forget.
git log Show the commit history.
git log
git log --oneline --graph --all # compact visual graph
git log -p src/auth.ts # commits that changed a specific file
git log --author="Jane" # filter by author
git log --since="1 week ago" git log --oneline --graph --all is the most useful variant — it shows all branches and merges visually. Add it as an alias: git config --global alias.lg "log --oneline --graph --all"
git diff Show what has changed between commits, branches, or in the working directory.
git diff # unstaged changes
git diff --staged # staged changes (what will be committed)
git diff main..feature/auth # difference between two branches git diff with no arguments shows unstaged changes. To see what you've already git add-ed, use git diff --staged.
git restore Discard changes in the working directory or unstage files (modern replacement for part of git checkout).
git restore src/file.ts # discard unstaged changes in a file
git restore --staged src/file.ts # unstage a file (keep changes)
git restore . # discard ALL unstaged changes git restore . is destructive — it permanently discards your uncommitted modifications. There is no undo. Make sure you really mean it.
git revert Create a new commit that undoes the changes from a previous commit — safe for shared branches.
git revert a1b2c3d # revert a specific commit
git revert HEAD~1 # revert the commit before the last one
git revert HEAD~3..HEAD # revert a range Revert is the safe undo for production branches. It adds a new commit and preserves history. Prefer revert over reset on shared branches.
git reset Move the branch pointer backwards in history, optionally changing staged/working-directory state.
git reset --soft HEAD~1 # undo last commit, keep changes staged
git reset --mixed HEAD~1 # undo last commit, keep changes unstaged (default)
git reset --hard HEAD~1 # undo last commit, DISCARD all changes NEVER use git reset --hard on commits that have been pushed. It rewrites history and you cannot recover the discarded changes. Only use reset on local, unpushed commits.
git cherry-pick Apply the changes from a specific commit onto the current branch.
git cherry-pick a1b2c3d # apply one commit
git cherry-pick a1b2c3d..e5f6g7h # apply a range Cherry-pick creates a new commit with a different hash. If the original commit later gets merged, you'll have duplicate changes. Use sparingly — a proper branch merge is usually cleaner.
git bisect Use binary search to find which commit introduced a bug.
git bisect start
git bisect bad # current commit is broken
git bisect good v2.1.0 # this tag/commit was working
# Git checks out a midpoint commit:
git bisect good # or: git bisect bad
# repeat — Git narrows down the culprit
git bisect reset # return to original HEAD Bisect is surprisingly fast — it finds the bad commit in O(log n) steps. For a history of 1000 commits, you only need ~10 checks.
git tag Mark a specific commit with a human-readable label, typically for releases.
git tag v1.0.0 # lightweight tag
git tag -a v1.0.0 -m "Release 1.0" # annotated tag with message
git push origin v1.0.0 # push a tag to remote
git push origin --tags # push all tags Tags are NOT pushed with git push by default. You must explicitly push tags. Annotated tags (-a) are preferred for releases as they store the tagger, date, and message.
git remote Manage connections to remote repositories.
git remote -v # list remotes
git remote add origin git@github.com:user/repo.git
git remote rename origin upstream
git remote remove origin By convention, the primary remote is called origin. A forked repo often has two remotes: origin (your fork) and upstream (the original project).
git config Set user-level or repo-level configuration options.
git config --global user.name "Jane Smith"
git config --global user.email "jane@example.com"
git config --global core.editor "code --wait"
git config --global alias.lg "log --oneline --graph --all"
git config --list # show all settings --global saves to ~/.gitconfig and applies everywhere. Without it, the setting is local to the current repo. Use --global for name/email/editor and local for per-project overrides.
Phrases you'll hear and use in code reviews, Slack messages, and standups.
`git merge` combines the history of another branch into the current one by creating a new merge commit with two parents, preserving the full history of both branches exactly as it happened. `git rebase` instead rewrites your branch's commits as if they started from the tip of the target branch, producing a linear history — but because it changes commit hashes, you should never rebase commits that have already been pushed to a shared branch.
`git reset --hard` moves the branch pointer backwards and discards the changes entirely — safe only on local, unpushed commits, because it rewrites history and there is no way to recover what was reset away. `git revert` instead creates a brand-new commit that undoes a previous one, leaving history intact, which is why it is the safe choice for undoing changes on a shared or production branch.
`git fetch` downloads remote commits into your local remote-tracking branches without touching your working directory — it is always safe and lets you inspect incoming changes first. `git pull` is shorthand for `git fetch` followed immediately by `git merge` (or, with `--rebase`, a rebase), so it does change your current branch, which is why `git fetch` is the safer default when you just want to see what changed upstream.
`git checkout` is the older, multi-purpose command that both switches branches and restores files from history, which made it easy to misuse. Git 2.23 split those responsibilities into `git switch` (branches only) and `git restore` (files only) for clarity, but `git checkout` still works exactly as before — they are equivalent for switching branches.
No — stashes are local only and never travel with `git push`. A stash is a quick way to shelve uncommitted changes so you can switch context (e.g. to fix an urgent bug on another branch), not a backup mechanism, so it should not be relied on to preserve work across machines or long periods.
`git restore` operates on files: it discards unstaged changes in the working directory or unstages files while keeping their content (`--staged`). `git reset` operates on the branch pointer itself, moving HEAD to a different commit and optionally changing what is staged or in the working directory along the way — the two commands were split apart from the older, overloaded `git checkout` for exactly this reason.
Cherry-pick applies the changes from a specific commit onto the current branch as a brand-new commit with a different hash, even though the content is identical to the original. If that original commit is later merged into the same branch through its normal branch history, Git has no way to recognize them as "the same change" by hash, and you can end up with duplicate changes or unnecessary conflict resolution.
No — tags are not included in a plain `git push` by default. You have to push them explicitly with `git push origin v1.0.0` for a single tag or `git push origin --tags` for all of them, and annotated tags (`git tag -a`) are generally preferred for releases since they store the tagger, date, and message, unlike lightweight tags.
Squashing means combining several small, incremental commits into a single commit, typically done with `git rebase -i HEAD~N` before merging a feature branch. It is common practice to squash noisy work-in-progress commits ("fix typo", "wip", "actually fix it") into one clean commit so the shared branch history reads as a single logical change.
Yes — every command, example, and gotcha on this page is free to read and reference whenever you need a quick reminder of what a Git command does or how it behaves.