DevOpsIndex

Git Common Fixes

1. reset --soft / --mixed / --hard

flowchart LR
    subgraph soft["--soft"]
        S1[HEAD moves] --> S2[Index unchanged]
        S2 --> S3[Working tree unchanged]
    end
    subgraph mixed["--mixed (default)"]
        M1[HEAD moves] --> M2[Index reset]
        M2 --> M3[Working tree unchanged]
    end
    subgraph hard["--hard"]
        H1[HEAD moves] --> H2[Index reset]
        H2 --> H3[Working tree reset]
    end
Mode HEAD Index (staged) Working tree
--soft ✅ moves unchanged unchanged
--mixed ✅ moves ✅ reset unchanged
--hard ✅ moves ✅ reset ✅ reset ⚠️
git reset --soft HEAD~1    # undo commit, keep staged
git reset --mixed HEAD~1   # undo commit + unstage, keep files
git reset --hard HEAD~1    # undo commit + discard all changes

2. Amend Last Commit

# Fix commit message only
git commit --amend -m "correct message"

# Add forgotten file
git add forgotten.go
git commit --amend --no-edit   # keeps existing message

# Already pushed? Must force push
git push --force-with-lease

3. Recover Deleted Branch with Reflog

flowchart TD
    A[Branch deleted] --> B[git reflog]
    B --> C["Find commit SHA<br/>e.g. abc1234"]
    C --> D[git checkout -b recovered abc1234]
    D --> E[Branch restored]
git reflog                          # find the tip commit of deleted branch
git checkout -b recovered abc1234   # recreate branch at that SHA
# or
git branch recovered abc1234

Reflog expires after 90 days by default.


4. Interactive Rebase

git rebase -i HEAD~4   # rewrite last 4 commits

In the editor:

pick a1b2c3 first commit
squash d4e5f6 fixup for first    # merge into previous
reword 7g8h9i bad message        # edit message
edit  j0k1l2 needs splitting     # pause to amend
drop  m3n4o5 mistake             # delete entirely
# During edit pause:
git add .
git commit --amend
git rebase --continue

# Abort at any time:
git rebase --abort

5. Cherry-pick

git cherry-pick abc1234             # apply single commit
git cherry-pick abc1234 def5678     # apply multiple commits
git cherry-pick abc1234..def5678    # apply a range (exclusive start)
git cherry-pick abc1234^..def5678   # apply a range (inclusive start)

# Conflict during cherry-pick:
git add .
git cherry-pick --continue
# or bail:
git cherry-pick --abort

6. git bisect

git bisect start
git bisect bad                  # current commit is broken
git bisect good v1.2.0          # this tag was working

# Git checks out midpoint — test it, then:
git bisect good   # or: git bisect bad

# Repeat until bisect prints the first bad commit
git bisect reset  # exit bisect mode

# Automate with a test script (exit 0 = good, non-zero = bad):
git bisect run ./test.sh

7. Detached HEAD

Detached HEAD = HEAD points to a commit SHA, not a branch ref.

git checkout abc1234   # → detached HEAD

# Save work before checking out something else:
git checkout -b save-detached-work   # create branch from current position
# or tag it:
git tag temp-save

If you already left without saving, find it in reflog:

git reflog | head -20   # look for "checkout: moving from"
git checkout -b recovered <sha>

8. Remove Committed Secrets

# Install git-filter-repo (preferred over filter-branch)
pip install git-filter-repo

# Remove a specific file from all history
git filter-repo --path secrets.env --invert-paths

# Replace a secret string everywhere in history
git filter-repo --replace-text <(echo "AKIAIOSFODNN7EXAMPLE==>REMOVED")

# After rewriting history, force push ALL branches
git push --force --all
git push --force --tags

Also: revoke the secret immediately. Assume it's compromised. Remove from all forks.


9. Merge Conflict Resolution

git merge feature-branch
# CONFLICT in src/handler.go

# Option A: use a mergetool
git mergetool   # opens vimdiff / VS Code / etc.

# Option B: manual edit
# In the file, resolve between <<<<<<< HEAD and >>>>>>> feature-branch
git add src/handler.go
git merge --continue   # or: git commit

# Abort entirely:
git merge --abort

# Useful during conflict resolution:
git diff                  # see all conflicts
git checkout --ours path   # accept our version
git checkout --theirs path # accept their version

10. Stash

git stash                      # stash tracked changes
git stash -u                   # include untracked files
git stash -m "wip: auth fix"   # named stash

git stash list                 # show all stashes
git stash show -p stash@{1}    # diff of a stash

git stash pop                  # apply latest + remove from list
git stash apply stash@{2}      # apply specific, keep in list
git stash drop stash@{1}       # delete specific stash
git stash clear                # delete all stashes ⚠️

# Stash only staged changes:
git stash --staged