DevTools

Cheatsheet Git

Sistema de controle de versão

Back to languages
Git
87 cards found
Categories:
Versions:

Introduction and Configuration


7 cards
What is Git (Quick History)

Git is a distributed version control system, created by Linus Torvalds in 2005 (the same creator of Linux) to replace BitKeeper in the development of the kernel.

Main features:

  • Distributed: each user has the complete repository locally, with all the history.
  • Fast: operations like commit, branch and merge are done locally, without network.
  • Secure: each change is protected by a SHA-1 hash, which makes the history practically tamper-proof.
View the configuration (git config --list)
git config --list
git config --global --list
git config user.name
git config --show-origin --list

The --list shows all active settings (system, global and local). To see just one value, pass the key, for example user.name. The --show-origin indicates which file (.gitconfig) each setting comes from — useful for resolving configuration conflicts.

Create repository (git init)
git init
git init my-project
git init --bare repository.git

git init creates the hidden .git folder with all the repository's internal structure. With a folder name, it also creates the directory. The --bare flag creates a repository without a working directory, used on servers.

Warning: if a .git folder already exists, don't run this again — you could corrupt the history.

Configuration levels: system, global, local

Git reads the configuration at three levels, from the most general to the most specific:

  • --system: the whole computer (file /etc/gitconfig).
  • --global: your user (file ~/.gitconfig).
  • --local: only the current repository (file .git/config) — it's the default level.

The most specific level always wins: a --local setting overrides --global, which overrides --system.

Clone an existing project (git clone)
git clone https://github.com/user/repository.git
git clone https://github.com/user/repository.git folder-local
git clone --depth 1 https://github.com/user/repository.git
git clone -b develop https://github.com/user/repository.git

git clone copies everything from the remote repository (history, branches, tags) to your machine and automatically creates the link to origin. The --depth 1 makes a shallow clone (only the last commit, faster). The -b clones a specific branch directly.

Check the version and get help
git --version
git help config
git config --help

git --version shows the installed version — useful to confirm whether you have recent features like git switch (Git 2.23+). The git help command opens the full manual of any command.

Configure user (git config)
git config --global user.name "Your Name"
git config --global user.email "email@example.com"
git config --global init.defaultBranch main
git config --global core.editor "code --wait"

Sets the identity that Git records in each commit. The --global flag applies to the whole user; without it, the configuration stays only in the current repository. The init.defaultBranch sets the name of the initial branch and core.editor the editor used for messages.

Basic Commands


10 cards
View the current status (git status)
git status
git status -s
git status --ignored

The most used command in Git. It shows the current branch, the changed files, those in staging (ready for the next commit) and the untracked ones. The -s gives a short version and the --ignored includes files ignored by .gitignore.

Commit modified files directly (-am)
git commit -am "Update dependencies"

The -a automatically adds all files that are already tracked and modified, skipping the git add. Warning: new files (untracked) are not included — those still need git add.

Ignore files (.gitignore)
node_modules/
.env
*.log
dist/
!dist/.gitkeep

The .gitignore file tells Git which files should not be tracked: dependencies (node_modules/), secrets (.env), logs and build artifacts. The ! negates a pattern (includes it back). Already-versioned files are not ignored — use git rm --cached first.

Add files to staging (git add)
git add file.php
git add .
git add -p
git add *.js

Staging is the "waiting room" before the commit: you choose exactly what goes in. The git add . adds everything; the -p (patch) lets you review and approve part by part of each file. Never commit blindly: git status + git add gives you full control.

View differences (git diff)
git diff
git diff --staged
git diff main..feature
git diff HEAD~3

git diff shows the changes outside staging; with --staged it shows what's already prepared for the next commit. You can compare two branches with main..feature or your work against an old commit with HEAD~3.

The three states of a file

Each file in Git lives in one of three states:

  • Working directory: the files the they are on your disk, with unsaved changes.
  • Staging area: what you prepared with git add for the next commit.
  • Repository: what has already been saved with git commit.

The normal flow is always: edit → git addgit commit.

Create a commit (git commit)
git commit -m "Message clara e useful"

A commit is a saved point on the project's timeline. Good messages save hours of debugging: describe what was done and why, not just "fix". Golden rule: short and direct title, up to 50 characters.

Remove files from the repository (git rm)
git rm file.txt
git rm -r folder/
git rm --cached file.txt

git rm deletes the file from the repository and from disk. The --cached removes only from the repository, keeping the local file — the correct way to stop versioning something that should go into .gitignore.

Commit with title and body
git commit -m "Add email validation" -m "Prevents records with invalid emails. Validates format and domain."

The first -m is the title; the second becomes the body of the message. Git reads the first line the the title — it should be short and direct. Use the body to explain the context and the reason for the change.

Rename or move files (git mv)
git mv old.php new.php
git mv file.php folder/

git mv renames or moves files while keeping the associated change history. It's the equivalent of doing mv + git add in a single step, and Git records the operation the a rename.

History and Inspection


10 cards
View full history (git log)
git log
git log -5
git log --stat

Shows the commit history of the current branch: IDs (SHA-1), authors, dates and messages. The -5 limits to the last five and the --stat adds a summary of the files changed in each commit.

Search code in the history (git log -S)
git log -S "functionName"
git log -S "functionName" --oneline

The -S (pickaxe) finds the commits that added or removed that text in the code — not just in the message. It's the right tool to discover in which commit a function or bug was introduced.

Find bugs with bisect
git bisect start
git bisect bad
git bisect good v1.0
git bisect reset

git bisect performs a binary search in the history: you mark a good commit (good) and a bad one (bad), and Git keeps testing the ones in between until it finds the exact commit that introduced the bug. The git bisect reset returns you to the original branch.

Summarized history (git log --oneline)
git log --oneline
git log --oneline -10

Shows each commit on a single line, with the abbreviated ID and the message. It's the fastest way to get a clean, overall view of the project's history.

View a specific commit (git show)
git show
git show a1b2c3d
git show a1b2c3d --stat

With no arguments, it shows the last commit with the full diff. With an ID (just the prefix is enough, e.g. a1b2c3d), it shows that commit. It also works to view the content of a tag or of a file at another point in the history.

Contribution statistics (git shortlog)
git shortlog -sn
git shortlog -sn --since="1 year ago"

git shortlog -sn groups the commits by author with the count, ordered from most active to least. Ideal for quick team activity reports.

Visual history of all branches
git log --oneline --graph --all
git log --graph --pretty=format:'%h %d %s (%an)' --all

Combines --oneline, --graph (ASCII drawing of the branches) and --all (all branches, not just the current one). It lets you quickly visualize the project's structure and how the branches connect at merges.

Who changed each line (git blame)
git blame file.php
git blame -L 10,20 file.php
git blame -w file.php

git blame shows, line by line, the last commit and the author who touched each one. The -L 10,20 limits to the range of lines and the -w ignores whitespace changes. Useful for understanding the origin of strange code — no judgment!

Filter the history
git log --author="Name"
git log --grep="word"
git log --since="2 weeks ago"
git log -- app/Models/

Filters commits by author (--author), by text in the message (--grep), by date (--since/--until) or by file path. Essential for finding "who did this" or "when did that bug appear".

Recover lost commits (git reflog)
git reflog
git reflog --date=iso
git checkout a1b2c3d

reflog records all the movements of HEAD — even commits "deleted" by a reset. It's Git's safety net: find the ID of the lost commit and recover it with git checkout or git reset. Nothing is truly lost.

Branches


9 cards
Create branch (git branch)
git branch feature/branch-name

Branches are "parallel universes" of your code: main is the official timeline and the rest are branches where you work without breaking anything. Most used conventions: feature/ (new features), bugfix/ (day-to-day bugs), hotfix/ (production emergencies) and release/ (preparing versions).

Create and switch at the same time
git checkout -b feature/login

Creates the feature/login branch and switches to it right away. It combines git branch (create) and git checkout (switch) in a single step — the fastest way to start a new feature.

Force delete + delete remote
git branch -D name
git push origin --delete name

The -D deletes the branch even without a merge — careful, unintegrated work is lost (although the reflog still keeps it for a while). The push origin --delete removes the branch from the remote repository.

View existing branches (git branch)
git branch
git branch -v
git branch --merged

Lists the local branches and marks with * the one you're on. The -v shows the last commit of each one and the --merged lists those already integrated into the current branch — good candidates for deletion.

git switch: the modern alternative
git switch branch-name
git switch -c feature/login
git switch -

git switch (Git 2.23+) does only the part of checkout that changes branch, without the dangerous side effects (like restoring files). The -c creates and switches, and the - returns to the previous branch.

View local and remote branches
git branch -a
git branch -r

The -a shows all the branches (local and remote); the -r only the remote ones (e.g. origin/main). The remote ones are "snapshots" of the server, updated with git fetch.

Rename a branch
git branch -m new-name
git branch -m name-old new-name

The -m renames the current branch (or the specified one). If the branch was already on the remote, you'll have to delete the old remote one with git push origin --delete and push the new one with -u.

Switch branch (git checkout)
git checkout branch-name

Updates the files in the working directory to reflect the chosen branch and moves the HEAD pointer to it. Git blocks the switch if there are unsaved changes that would conflict — use git stash in those cases.

Delete local branch (safe)
git branch -d name

git branch -d deletes the branch only if it has already been integrated (merged) into another. It's the safe way to clean up branches that are no longer needed, with no risk of losing work.

Merge and Rebase


8 cards
Merge (normal join)
git checkout main
git merge bugfix/branch-name

git merge creates a merge commit that joins the branch's work into the current one, preserving the history the it happened. Great for teams, because it records when and how each feature was integrated.

Abort merge or rebase
git merge --abort
git rebase --abort

If a merge or rebase went wrong (impossible conflicts, for example), the --abort cancels the operation and returns everything to the previous state, with no damage. It's the official "panic button".

Merge without fast-forward (--no-ff)
git merge --no-ff feature/login

By default, if the branch hasn't diverged, Git just advances the pointer (fast-forward) and the merge becomes invisible in the history. The --no-ff forces the creation of the merge commit, keeping visible that that feature existed the a branch.

Resolve conflicts
<<<<<<< HEAD
your code
=======
code from the other branch
>>>>>>> branch-name

When Git can't join two versions of the same line, it marks the file with <<<<<<< HEAD, ======= and >>>>>>>. Steps: open the file, choose what to keep (you can mix or rewrite), remove the markers, save and finish with git add . and git commit.

Merge squash (--squash)
git checkout main
git merge --squash feature/login
git commit -m "Add login"

The --squash joins all the branch's commits into a single set of changes, which you commit manually. Ideal for turning branches with dozens of "wip" commits into a single clean commit on main.

Cherry-pick: apply a specific commit
git cherry-pick a1b2c3d
git cherry-pick a1b2c3d b2c3d4e
git cherry-pick --no-commit a1b2c3d

Applies a specific commit (by ID) to the current branch, without merging the whole branch. Useful for bringing an urgent fix into the release without dragging the rest of the feature. The --no-commit applies the changes without committing.

Rebase (linear history)
git checkout feature
git rebase main

"Teleports" your commits the if they had been made after the latest ones on main, leaving the history linear and clean. Dangerous on branches shared on the remote: rewriting someone else's history causes conflicts and lost work.

Merge vs Rebase: when to use

Merge: preserves the real history, creates merge commits, safe on shared branches. Use it when you work in a team on the remote.

Rebase: rewrites the history to be linear, cleaner to read. Use it only on local and personal branches, before doing push.

Golden rule: never rebase on public branches that others also use.

Remote


10 cards
Link local repository to the remote
git remote add origin https://github.com/user/repo.git

Adds the remote repository with the name origin (convention for the main remote). From here you can use git push and git fetch to sync with GitHub, GitLab or Bitbucket.

git pull: fetch + merge
git pull
git pull origin main

Brings the changes from the remote and applies them automatically to your current branch. It's the equivalent of git fetch + git merge. If there are divergences, it can generate conflicts or a merge commit.

Push with upstream (-u)
git push -u origin branch-name

Sends the branch and links it to the remote (sets the upstream). From then on, git push and git pull work with no arguments — Git already knows where the code comes from and goes to.

View remote repositories (git remote -v)
git remote
git remote -v
git remote show origin

Lists the configured remotes. The -v shows the fetch and push URLs (lets you confirm whether you're using HTTPS or SSH). The git remote show origin gives the full detail: tracked branches and sync status.

pull vs fetch

git fetch: downloads the news but doesn't touch your code — safe to peek. git pull: downloads and integrates right into your branch. When in doubt, use fetch first, see what changed with git log origin/main, and only then decide between merge or rebase.

Safe force push (--force-with-lease)
git push --force-with-lease
git push --force

After a rebase, the history diverges from the remote and the normal push is refused. The --force overwrites the remote blindly and dangerously; the --force-with-lease only advances if no one has sent new commits — always use this one.

Rename or remove a remote
git remote rename origin upstream
git remote remove upstream

The rename changes a remote's name (and updates all the references). The remove deletes the link — your local commits are not affected, you just can no longer push/pull to that address.

git pull --rebase (linear history)
git pull --rebase
git config --global pull.rebase true

Brings the changes from the remote and reapplies your commits on top, without creating merge commits. It keeps the history clean and linear. You can make this behavior the default with the pull.rebase true configuration.

git fetch: look without touching
git fetch
git fetch origin
git fetch --all --prune

Downloads the news from the remote (new commits, branches) without changing your local work — you can inspect before deciding. The --prune deletes the local references to remote branches that have already been deleted on the server.

Send changes (git push)
git push origin branch-name
git push

Sends the commits of your local branch to the origin remote. If the branch doesn't exist on the remote, it's created. After setting the upstream (see the next card), just git push.

Stash


8 cards
Save changes without committing (git stash)
git stash
git stash push

Saves the uncommitted changes and returns the working directory to the clean state of the last commit. Perfect when you need to switch branch "right now" without losing the work in progress.

Apply a stash (git stash apply)
git stash apply
git stash apply stash@{2}

git stash apply reapplies the saved changes to the working directory without removing the stash from the list — you can apply it on several branches or keep the backup copy.

Stash with a message
git stash push -m "WIP: form de login"

The -m flag gives a message to the stash — essential to identify it in the list when you have several saved. Without it, Git uses the generic WIP on branch... message, hard to tell apart.

Apply and remove (git stash pop)
git stash pop

Applies the most recent stash and removes it from the list, in a single step. It's the normal flow: you saved with git stash, you return to work with git stash pop.

Stash with untracked files (-u)
git stash -u
git stash --include-untracked

By default, the stash ignores new (untracked) files. The -u includes them — useful when you created files that hadn't yet had a git add.

Remove a specific stash
git stash drop stash@{0}

Deletes a stash from the list without applying it. Use the identifier you see in git stash list — for example stash@{1} for the second most recent.

View the list of stashes
git stash list
git stash show stash@{1}
git stash show -p stash@{1}

Lists all the stashes with identifiers stash@{0}, stash@{1}, etc. (the {0} is the most recent). The show summarizes the changes and the -p shows the full diff — so you can see what you saved before applying.

Delete all stashes
git stash clear

Deletes all the stashes at once. Warning: there's no confirmation nor a reflog that returns them easily — confirm with git stash list first.

Undo Changes


8 cards
Fix the last commit (--amend)
git commit --amend -m "New message"
git add file-esquecido.php
git commit --amend --no-edit

Rewrites the last commit: changes the message or adds forgotten files (with --no-edit it keeps the message). Only on local commits — doing an amend on an already-sent commit rewrites the history and causes confusion on the remote.

Discard changes in a file (git restore)
git restore file.php
git restore .

Reverts the file to the state of the last commit, discarding the unsaved changes. It's the modern replacement for the old git checkout -- file. Warning: discarded changes are not recoverable.

Remove the last commit keeping changes
git reset HEAD~1
git reset HEAD~3

Undoes the last commit but keeps the changes in the working directory (mixed mode, the default). The number after the ~ indicates how many commits to go back: HEAD~3 removes the last three.

Undo a commit with another commit (git revert)
git revert a1b2c3d
git revert HEAD

Creates a new commit that cancels the changes of the indicated commit, without touching the history. It's the only safe way to undo on shared branches — unlike reset, which rewrites the past.

The three reset modes
git reset --soft HEAD~1
git reset --mixed HEAD~1
git reset --hard HEAD~1

--soft: removes the commit, keeps everything in staging. --mixed (default): removes the commit and the staging, keeps the files. --hard: deletes everything — commit, staging and changes on disk. The --hard is destructive: use it only when sure.

Clean untracked files (git clean)
git clean -n
git clean -f
git clean -fd
git clean -fdx

Deletes untracked files from the working directory. The -n is a dry run (shows what would be deleted, without deleting); the -f forces, the -d includes folders and the -x also those ignored by the .gitignore. Always do -n first.

Take files out of staging (git restore --staged)
git restore --staged file.php
git restore --staged .

Undoes the git add: the file leaves the staging area but the changes stay on disk. It lets you fix what will go into the next commit without losing work.

reset vs revert vs restore

git reset: moves the HEAD pointer back — rewrites the history, only for local commits. git revert: creates a commit that cancels another — safe on the remote. git restore: undoes changes in files (on disk or in staging), without touching commits. Simple rule: local → reset; shared → revert; files → restore.

Advanced


9 cards
Interactive rebase (rebase -i)
git rebase -i HEAD~3
git rebase --continue

Opens an editor with the last 3 commits for you to rewrite them: change the order, join (squash), rename (reword) or delete (drop). After saving, continue with git rebase --continue. Ideal to clean up "wip" commits before a push.

Git Hooks
# .git/hooks/pre-commit
#!/bin/sh
php artisan test

The hooks are scripts run automatically at key points: pre-commit (before each commit — ideal to run tests or linters), commit-msg (validate the message), pre-push, etc. They live in the .git/hooks/ folder and are not versioned by default.

Maintenance (git gc)
git gc
git prune
git count-objects -v

The git gc (garbage collection) compresses the history and removes unreachable objects, keeping the .git folder small and fast. Git already runs it automatically from time to time; force it on very old repositories or after big cleanups.

Interactive rebase commands

In the rebase -i editor, each line starts with a command:

  • pick: keeps the commit the it is.
  • reword: keeps it but edits the message.
  • squash: joins it to the previous commit (keeping the messages to edit).
  • fixup: joins it to the previous one, discarding the message.
  • drop: deletes the commit.
  • edit: stops at that commit for you to change it (with --amend).
Archive the project (git archive)
git archive -o release-v1.0.zip v1.0.0
git archive --format=tar.gz --prefix=app/ HEAD > app.tar.gz

Exports the state of the project at a given point (tag, branch or commit) to a zip or tar — without the .git history. Ideal to deliver releases or make backups of the code.

Tags (git tag)
git tag v1.0.0
git tag -a v1.0.0 -m "Version 1.0.0"
git tag -l "v1.*"
git push origin v1.0.0
git push origin --tags

Tags mark fixed points of the history, usually versions (v1.0.0). The annotated ones (-a) store author, date and message. Tags do not go to the remote automatically — use git push origin --tags.

Aliases: custom shortcuts
git config --global alias.st status
git config --global alias.co checkout
git config --global alias.lg "log --oneline --graph --all"

The aliases create shortcuts for the commands you use most. After alias.st status, you just write git st. The classic git lg gives you the full visual history with three keys.

Worktrees: several branches at the same time
git worktree add ../project-hotfix hotfix/urgent
git worktree list
git worktree remove ../project-hotfix

The worktree creates a second working folder of the same repository, on another branch — without duplicated clones. Perfect to fix an urgent bug without saving what you have in hand with stash.

Submodules
git submodule add https://github.com/lib/dependency.git libs/dep
git submodule update --init --recursive
git clone --recurse-submodules URL

The submodules embed another repository inside yours, with the version pinned at a specific commit. After cloning a project with submodules, the --init --recursive downloads them. Modern alternatives: packages via composer or npm.

Extras and Good Practices


8 cards
Vim: enter edit mode

When Git opens vim (on a commit without -m, for example), you're in normal mode — the keys don't write. To edit, press:

  • i → insert where the cursor is
  • a → insert after the cursor
  • o → create a new line below

You'll see -- INSERT -- at the bottom. To return to normal mode, press Esc.

Git Emojis: performance and security

PERF – Performance improvements. Ex.: ⚡ PERF: optimize database query.

🔒 SECURITY – Vulnerability fix. Ex.: 🔒 SECURITY: prevent SQL Injection in the login.

🚑 HOTFIX – Urgent fix in production. Ex.: 🚑 HOTFIX: fix downtime in payments.

🗑 REMOVE – Remove obsolete code or files. Ex.: 🗑 REMOVE: delete old tests.

Vim: save and exit

In normal mode (after Esc):

  • :w — save (write)
  • :q — exit (quit)
  • :wq — save and exit
  • :q! — exit without saving
  • :x — save and exit, but only if there were changes

If you got stuck in the editor during a commit: Esc, then :wq and Enter.

Anatomy of a good commit message

A good git commit message has three parts:

  • Title (up to 50 characters): imperative and direct — "Add email validation", not "added".
  • Blank line to separate.
  • Body (optional): explains the why and the context, not the how (the code shows that).

If the title needs an "and", it's probably two commits.

Git Emojis: features and fixes

📦 NEW – Add a new feature or module. Ex.: 📦 NEW: create authentication module with Google.

ADD – Add simple code to something already existing. Ex.: ➕ ADD: add "phone" field to the record.

🐛 FIX – Fix an error or unexpected behavior. Ex.: 🐛 FIX: fix failure in email validation.

👌 IMPROVE – Improve existing code (performance, readability). Ex.: 👌 IMPROVE: optimize dashboard loading.

🚀 RELEASE – Publish a new version. Ex.: 🚀 RELEASE: version 1.2.0 released.

Recommended daily workflow
git status
git add .
git commit -m "📦 NEW: add pagination"
git pull --rebase
git push

The safe day-to-day cycle: check the state with git status, prepare with git add, save with git commit, sync with git pull --rebase (resolve conflicts locally) and only then send with git push.

Git Emojis: documentation, style and tests

📝 DOCS – Documentation updates. Ex.: 📝 DOCS: update README com instructions de installation.

🖌 STYLE – Style/formatting changes (without affecting logic). Ex.: 🖌 STYLE: adjust colors e position dos buttons.

🐳 DOCKER – Changes in Docker configurations or images. Ex.: 🐳 DOCKER: update container base image.

REFACTOR – Refactoring without changing behavior. Ex.: ♻ REFACTOR: divide func big em methods menores.

TEST – Add or improve automated tests. Ex.: ✅ TEST: tests unit to authentication.

Branch naming conventions

Consistent names keep the repository predictable:

  • feature/name — new feature (born from main/develop).
  • bugfix/name — day-to-day bug, not critical.
  • hotfix/name — urgency in production.
  • release/1.2.0 — version preparation (changelog, final tests).

Use lowercase and hyphens (feature/login-social) and be specific: fix-bug says nothing to anyone.