cross-repo-cherry-pick — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited cross-repo-cherry-pick (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
You have two git repositories with unrelated histories:
You want to bring specific commits — or a contiguous range, or "everything since commit X" — from source into target. Crucially:
This is harder than it sounds because:
git cherry-pick works only when commits live in the same DAG.git format-patch + git am fails across repos because patches reference parent blob SHAs that don't exist in the target.In the source repo:
# range: from <start>^ (exclusive) to <end> (inclusive)
git diff --name-status <start>^..<end>Output is M for modified, A for added, D for deleted, R for renamed. List of files is your work scope.
For a single commit:
git diff --name-status <commit>^..<commit>Don't trust assumptions. Check actual bytes per file in both repos.
# In source repo — what's in the git blob (typically LF)
git show HEAD:<file> | head -1 | od -c | head -1
# In source repo working tree — what's on disk (often CRLF after Windows checkout)
head -1 <file> | od -c | head -1
# In target repo — what's in HEAD
git -C <target> show HEAD:<file> | head -1 | od -c | head -1You're looking for \r \n (CRLF) vs just \n (LF) at the end of the first line.
Common findings:
| Source git blob | Source working tree | Target git blob | Implication |
|---|---|---|---|
| LF | CRLF (autocrlf checkout) | LF | Easy — extract from blob, write to target |
| LF | CRLF | CRLF | Extract from blob, convert LF→CRLF, write |
| LF | CRLF | Mixed (some files LF, some CRLF) | Per-file detection required |
A 17-year-old PHP codebase that has been touched by both Windows and Linux editors will be inconsistent — some files LF, some CRLF, in the same repo.
# Get the LF-correct content of the source file at HEAD (or any commit)
git -C <source> show HEAD:<file> > /tmp/blob-contentThis gives you exactly what's in git, with no checkout-time conversion.
Per file, check target's line ending and convert if needed:
# Detect target's convention for a file
target_ending=$(git -C <target> show HEAD:<file> 2>/dev/null | head -c 4096 | grep -c $'\r')
# If $target_ending > 0, target uses CRLF for this file
if [ "$target_ending" -gt 0 ]; then
sed 's/$/\r/' /tmp/blob-content > /tmp/final-content
else
cp /tmp/blob-content /tmp/final-content
fi
cp /tmp/final-content <target>/<file>cd <target>
git status -s # files changed
git diff --stat # raw diff (will look huge if lines differ)
git diff --stat --ignore-all-space # real content deltaExpect a discrepancy: if a file had CRLF in source-git's blob (rare) but you wrote LF to target, every line will show as changed in the raw diff. The --ignore-all-space view is the source of truth for "what content actually changed."
If the --ignore-all-space numbers match what the source commits' git log --stat showed, you applied the changes correctly.
cd <target>
git checkout -b dev # if not already on a non-deployed branch
git add -A
git commit -m "$(cat <<'EOF'
feat: apply <feature-name> from <source-repo> to prod-mirror
Cherry-picks commits <range> from <source-repo>:
<commit-sha-1> <message-1>
<commit-sha-2> <message-2>
...
Files:
- <file-1>
- <file-2>
Note: line endings normalized to <LF|CRLF|mixed> to match target convention.
Real content delta (ignoring whitespace): +X / -Y lines.
EOF
)"Push to a branch that does not auto-deploy. If your CI deploys on main push, push to dev or any other branch.
For when you trust the protocol:
#!/usr/bin/env bash
# cross-repo-cherrypick.sh <source-repo-dir> <target-repo-dir> <range>
# e.g.: ./cross-repo-cherrypick.sh ~/old-dev ~/prod-mirror 6548e50^..HEAD
set -euo pipefail
SRC="$1"
DST="$2"
RANGE="$3"
# 1. List files
files=$(git -C "$SRC" diff --name-only "$RANGE")
# 2. For each file, extract from source blob, match target convention, write
while IFS= read -r f; do
[ -z "$f" ] && continue
mkdir -p "$DST/$(dirname "$f")"
# Extract source content (blob — LF normalized)
src_content=$(git -C "$SRC" show "HEAD:$f" 2>/dev/null) || {
echo "MISSING in source HEAD: $f"
continue
}
# Detect target convention (default to LF if file doesn't exist yet)
target_uses_crlf="no"
if [ -f "$DST/$f" ]; then
if head -c 4096 "$DST/$f" | grep -q $'\r'; then
target_uses_crlf="yes"
fi
fi
# Write with appropriate line ending
if [ "$target_uses_crlf" = "yes" ]; then
printf '%s' "$src_content" | sed 's/$/\r/' > "$DST/$f"
else
printf '%s' "$src_content" > "$DST/$f"
fi
echo "OK $f"
done <<< "$files"
echo "Done. Run \`cd $DST && git diff --stat --ignore-all-space\` to verify."When you see a "huge git diff that doesn't make sense":
git show <ref>:<file> | head -1 | od -c | head -1.head -1 <file> | od -c | head -1.sed 's/\r$//' (CRLF→LF) or sed 's/$/\r/' (LF→CRLF).The pattern: `git diff` output is very rarely lying about content. It IS often lying about how much you actually changed, because line endings inflate the apparent diff. Always cross-check with --ignore-all-space.
In one engagement, this exact problem ate ~45 minutes:
git am with patch files. ❌ Broken — blob SHAs don't exist across repos.git apply --3way. ❌ Broken — same SHA problem.The trial-and-error was costly because every attempt produced a "huge diff" that looked plausible at first glance — you have to dig in to realize it's line-ending noise. Skip the chain by using this protocol from step 1.
--ignore-all-space. The real number is usually 5–10% of the displayed number.When you complete a cross-repo cherry-pick, produce a summary:
Source: <repo> <range>
Target: <repo> <branch>
Files: <count> (M: ..., A: ..., D: ...)
Raw diff: +<X> / -<Y>
Content diff: +<X'> / -<Y'> (--ignore-all-space)
Line-ending noise: <X-X'> + <Y-Y'>
Commit: <sha>
Branch: <branch> (push manually when ready)This makes the actual scope of the change reviewable.
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.