Fix linearize fallback applying wrong diff (full tree instead of parent)
The fallback for failed cherry-picks used `git diff HEAD $sha` which
computes the diff between the linearize branch and the commit's full
tree. This captures ALL tree differences, not just the changes the
commit introduced — causing unrelated file deletions.
Fix: diff from the commit's own parent (`${sha}^` for regular commits,
`${sha}^1` for merge commits). Also detect and skip empty merges
(where cherry-pick -m 1 produces nothing because the changes were
already applied by a prior cherry-pick).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
22
lib/sync.sh
22
lib/sync.sh
@@ -339,14 +339,16 @@ reverse_sync() {
|
||||
if git cherry-pick "$sha" >/dev/null 2>&1; then
|
||||
log "INFO" " cherry-pick ${sha:0:7}: ${short_msg}"
|
||||
else
|
||||
log "WARN" " conflict ${sha:0:7} — applying tree directly"
|
||||
log "WARN" " conflict ${sha:0:7} — applying patch from parent"
|
||||
git cherry-pick --abort 2>/dev/null
|
||||
local msg author_name author_email author_date
|
||||
msg=$(git log -1 --format="%B" "$sha")
|
||||
author_name=$(git log -1 --format="%an" "$sha")
|
||||
author_email=$(git log -1 --format="%ae" "$sha")
|
||||
author_date=$(git log -1 --format="%aI" "$sha")
|
||||
git diff HEAD "$sha" | git apply --index >/dev/null 2>&1 \
|
||||
# Diff from the commit's own parent — NOT from HEAD (which is
|
||||
# the linearize branch and may have a different base).
|
||||
git diff "${sha}^" "$sha" | git apply --index >/dev/null 2>&1 \
|
||||
|| die "Failed to apply diff for ${sha:0:7}"
|
||||
GIT_AUTHOR_NAME="$author_name" GIT_AUTHOR_EMAIL="$author_email" \
|
||||
GIT_AUTHOR_DATE="$author_date" \
|
||||
@@ -362,17 +364,27 @@ reverse_sync() {
|
||||
author_date=$(git log -1 --format="%aI" "$sha")
|
||||
|
||||
if git cherry-pick -m 1 "$sha" >/dev/null 2>&1; then
|
||||
: # success
|
||||
log "INFO" " squash ${sha:0:7}: ${short_msg}"
|
||||
else
|
||||
git cherry-pick --abort 2>/dev/null
|
||||
git diff HEAD "$sha" | git apply --index >/dev/null 2>&1 \
|
||||
# Diff from first parent — what the merge actually introduced.
|
||||
# NOT from HEAD (which would capture all tree differences, not
|
||||
# just this merge's changes).
|
||||
if git diff "${sha}^1" "$sha" --quiet 2>/dev/null; then
|
||||
# Empty diff from first parent — the merge introduced no new
|
||||
# changes (e.g., a fast-forward merge or changes already applied
|
||||
# by a prior cherry-pick). Skip silently.
|
||||
log "INFO" " skip ${sha:0:7}: ${short_msg} (empty — already applied)"
|
||||
else
|
||||
git diff "${sha}^1" "$sha" | git apply --index >/dev/null 2>&1 \
|
||||
|| die "Failed to apply merge diff for ${sha:0:7}"
|
||||
GIT_AUTHOR_NAME="$author_name" GIT_AUTHOR_EMAIL="$author_email" \
|
||||
GIT_AUTHOR_DATE="$author_date" \
|
||||
git commit -m "$msg" >/dev/null 2>&1 || die "Failed to commit merge ${sha:0:7}"
|
||||
fi
|
||||
log "INFO" " squash ${sha:0:7}: ${short_msg}"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
log "INFO" "─── linearize done ────"
|
||||
|
||||
Reference in New Issue
Block a user