From 1906c3182231e3f4a0831a54a918a5f5af3beffb Mon Sep 17 00:00:00 2001 From: Sebastian Mendel Date: Wed, 5 Aug 2026 22:08:56 +0200 Subject: [PATCH] docs(advanced-git): merge-tip rebase collapse, no tail-piped gates, named staging, worktree .git file Four promoted traps; also removes a tail-pipe from this file's own cleanup example (the pattern the new section bans). Signed-off-by: Sebastian Mendel --- skills/git-workflow/references/advanced-git.md | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/skills/git-workflow/references/advanced-git.md b/skills/git-workflow/references/advanced-git.md index ff4794e..710c520 100644 --- a/skills/git-workflow/references/advanced-git.md +++ b/skills/git-workflow/references/advanced-git.md @@ -493,7 +493,7 @@ When removing a worktree leaves a dangling branch reference (e.g., after deletin ```bash # For each branch whose PR landed, delete the worktree + local branch: for wt in feature-x bugfix-y sync/template-foo; do - git -C /projects//.bare worktree remove --force /projects//$wt 2>&1 | tail -1 + git -C /projects//.bare worktree remove --force /projects//$wt git -C /projects//main branch -D "$wt" 2>&1 | tail -1 done @@ -1037,3 +1037,19 @@ gh api repos/OWNER/REPO/compare/... \ Verify against `origin` (or the compare API) before deleting a tag, choosing a release version, or concluding two lines forked — not against local refs. + +## Rebasing a branch whose tip is a merge commit can collapse the PR + +Plain `git rebase base` flattens/omits merge commits and skips patches whose patch-id is already upstream — if the branch's unique content lives *inside* a merge resolution, the rebase silently drops it, the branch becomes equal to base, and GitHub auto-closes the now-empty PR (content survives only in local reflog). After any batch rebase, verify `compare base...branch` shows `ahead >= 1` — `ahead = 0` means collapsed. Use `--rebase-merges` when the merge structure carries content. (Real case: a release-merge tip carried the feature edits; rebase → branch == main → PR auto-closed.) + +## Never pipe state-changing git/CLI commands through tail/head in `&&` chains + +`git pull --rebase 2>&1 | tail -1 && git tag …` is a double trap: the chain's exit code is tail's (always 0), and the one shown line is usually not the error. Burned repeatedly: tags created on stale pre-merge HEADs, a rejected push that "succeeded" on screen, a failed verification build that printed OK and let the push through. Gate steps run unpiped — redirect to a log, check `$?`, then read the log. Compounding race: `glab mr merge` returns before the merge commit exists, so an immediate pull can still see the old HEAD. + +## Stage by name — never `git add -A`/`.` when legacy untracked files exist + +A tree can hold untracked files the user explicitly keeps untracked; `-A`/`.` sweeps them into the commit, and after a push the cleanup needs a second commit (the add+delete stays in history). The staging step after a change is always: named files, or a named directory you fully own. + +## Bulk sed/rename across a worktree must not touch its `.git` FILE + +A linked worktree's `.git` is a file holding a `gitdir:` pointer, not a directory — `--exclude-dir=.git` does NOT protect it, and a blind `sed -i` over `grep -rl` output rewrites the pointer and breaks the worktree (`fatal: not a git repository`). Exclude the path explicitly (`grep -rl --exclude=.git` or filter the file list) before any bulk edit.