1 min read #devops
On this page

Git Operations Manual

delta is a modern alternative to git diff: it provides a sidebar, line numbers, and syntax highlighting. Configuration: git config --global pager.diff delta && git config --global pager.log delta

# Commit history
git log --oneline -20
git log --oneline --graph --all          # Visualize all branches
git log -p <file>                        # Diff for each change in a specific file
git log --since="2025-01-01" --until="2025-01-15"
git log --author="name" --oneline
git log -S "function_name"               # Search for commits that introduced/removed a piece of code (pickaxe)
git log -G "regex"                       # Same as above, but using regex

# Who changed what
git blame <file> -L 40,60

# Binary search for the commit that introduced a bug
git bisect start
git bisect bad HEAD                      # Current version is problematic
git bisect good v1.0                     # v1.0 was fine
# → Git checks out an intermediate version → test → git bisect good/bad → ... → locate the first bad commit
git bisect reset                         # End bisect session

# Recover lost commits
git reflog                               # Record of all HEAD movements (last 30 days)
git reflog show feature-branch           # Reflog for a specific branch
# → Find the hash of the reset/dropped commit → git checkout -b recovery <hash>

Branches and Merges

git branch                               # List local branches
git branch -r                            # List remote branches
git branch -a                            # List all branches
git checkout -b feature                  # Create and switch to a new branch

# merge: preserves branch history, creates a merge commit
git merge feature
# Use case: Merging a feature branch into main, preserving the information that "this feature was developed separately"

# rebase: moves the current branch's commits to the end of the target branch, creating a linear history
git rebase main
# Use case: Aligning a feature branch with main before submitting a PR, keeping a linear history

# When rebase conflicts occur:
git rebase --continue                    # Continue after resolving conflicts
git rebase --skip                        # Skip the current commit
git rebase --abort                       # Cancel the entire rebase

# cherry-pick: pick a single commit from another branch
git cherry-pick <commit-hash>
# Use case: Merging only a specific bug fix into a release branch, without bringing in other changes

# Delete branches that have been merged
git branch --merged main | grep -v 'main' | xargs git branch -d

Stashing and Undoing

# Stash current changes (before switching branches)
git stash
git stash save "description"
git stash list
git stash pop                            # Restore the most recent stash and delete it
git stash apply stash@{1}                # Restore a specific stash without deleting it
git stash drop stash@{1}
git stash clear                          # Clear all stashes

# Undoing
git reset --soft HEAD~1                  # Undo the most recent commit, keeping changes in the staging area
git reset --mixed HEAD~1                 # Undo the most recent commit, keeping changes in the working tree (default)
git reset --hard HEAD~1                  # Undo the most recent commit, discarding all changes (irreversible!)
git checkout -- <file>                   # Discard unstaged changes (irreversible)
git restore <file>                       # Same as checkout -- (newer command)
git restore --staged <file>              # Unstage a file (move from staging area to working tree)

# Undoing a commit that has already been pushed (remote):
git revert <commit-hash>                 # Create a reverse commit (safe, does not modify history)
# vs reset: revert is suitable for public branches (does not break others' history), reset is suitable for local branches

Remote

git remote -v
git remote add upstream https://github.com/original/repo.git
git fetch upstream                       # Fetch all remote branches, do not merge
git fetch --prune                        # Also delete local references that no longer exist on the remote
git pull --rebase                        # fetch + rebase (recommended, avoids meaningless merge commits)

# Safe force push: only push if the remote hasn't been changed by others
git push --force-with-lease
# Safer than --force: if a colleague pushed after your last fetch, this will reject the push, preventing overwrites

Submodule

git submodule update --init --recursive  # Fetch all submodules after initial clone
git submodule update --remote            # Update submodules to their latest commits
git submodule foreach git pull origin main

Worktree

# Check out different branches in different directories within the same repo (no need to clone twice)
git worktree add ../hotfix hotfix-branch
# → The ../hotfix directory is the working tree for hotfix-branch, without affecting the current directory

git worktree list
git worktree remove ../hotfix
# Use case: Fixing a bug in another branch while running long tests

Tag

git tag v1.0.0                           # Lightweight tag
git tag -a v1.0.0 -m "Release v1.0.0"    # Annotated tag (recommended)
git tag -d v1.0.0                        # Delete local tag
git push origin v1.0.0                   # Push a single tag
git push --tags                          # Push all tags