Cherry-pick

git cherry-pick מעתיק commit ספציפי מ-branch אחד אל ה-branch הנוכחי. השם בא מהדימוי של "לקטוף דובדבן" - לבחור בדיוק את מה שאתם רוצים.

מתי להשתמש?

  • תיקון באג ב-feature branch שצריך גם ב-main דחוף
  • העברת commit אחד מ-branch ניסוי ל-branch אמיתי
  • "צ'יפ" של commit מ-PR שעוד לא התקבל
  • Hotfix שצריך גם ב-release branch ישן

פקודה בסיסית

git cherry-pick a3f5c2d

git ייצור commit חדש ב-branch הנוכחי שלכם עם אותם השינויים של a3f5c2d. ה-SHA של ה-commit החדש יהיה שונה.

מספר commits

# commit אחד
git cherry-pick a3f5c2d

# מספר commits
git cherry-pick a3f5c2d b8e7f1a c9d2e3b

# טווח (לא כולל את הראשון)
git cherry-pick a3f5c2d..c9d2e3b

# טווח (כולל את הראשון)
git cherry-pick a3f5c2d^..c9d2e3b

דגלים שימושיים

git cherry-pick -x <commit>            # מוסיף "(cherry picked from commit ...)" להודעה
git cherry-pick -e <commit>            # פותח עורך לעריכת ההודעה
git cherry-pick -n <commit>            # רק staging, בלי commit אוטומטי
git cherry-pick --signoff <commit>     # מוסיף Signed-off-by

כשיש קונפליקט

cherry-pick יכול להיכשל אם ה-commit נוגע בקוד שכבר השתנה ב-branch הנוכחי. הזרימה זהה ל-merge:

git cherry-pick a3f5c2d
# CONFLICT (content): Merge conflict in src/login.js

# פותרים את הקונפליקט ידנית, מסמנים
git add src/login.js

# ממשיכים
git cherry-pick --continue

# או מבטלים
git cherry-pick --abort

דוגמת זרימה: hotfix ל-release ישן

# מצב: גילית באג ב-v1.0 שתיקנת ב-main
# צריך להחזיר את התיקון גם ל-release/v1.0

# 1. מוצאים את ה-commit של התיקון ב-main
git log --oneline | grep "fix login"
# a3f5c2d Fix login race condition

# 2. עוברים ל-release branch
git switch release/v1.0

# 3. cherry-pick של התיקון
git cherry-pick a3f5c2d

# 4. אם הקוד שונה - פותרים קונפליקט, ממשיכים
git add .
git cherry-pick --continue

# 5. דוחפים
git push origin release/v1.0

הבעיה עם cherry-pick

cherry-pick יוצר שני commits עם אותו תוכן אבל hash שונה. זה יכול לסבך merges עתידיים:

main:           A───B───C───D───E
                            \
release/v1.0:                F───G───D'  (D' = cherry-pick של D)

אם בעתיד תנסה למזג release/v1.0 ל-main, git ינסה להוסיף את D' ל-main - שכבר יש בו את D. בדרך כלל git חכם מספיק לזהות את זה, אבל לפעמים נוצרים קונפליקטים מיותרים.

מסקנה: cherry-pick הוא כלי שימושי, אבל לא ה-default. אם אפשר לעשות merge - עדיף.

דוגמה: cherry-pick של מספר commits עוקבים

# רוצים את 3 ה-commits האחרונים מ-feature/auth
git switch main
git cherry-pick feature/auth~2..feature/auth

# זה מעתיק 3 commits: feature/auth~2, feature/auth~1, feature/auth

דוגמה: cherry-pick רק עם staging

# רוצים לקחת commit אבל לערוך אותו לפני ה-commit החדש
git cherry-pick -n a3f5c2d

# עכשיו השינויים ב-staging אבל אין commit
git status

# עורכים, מוסיפים שינויים, מבצעים commit
git commit -m "Adapted login fix from main"

בדקו את עצמכם

נסו לענות לבד לפני שאתם פותחים את התשובה.

  1. מה עושה git cherry-pick <hash>?

    1. משנה הודעה
    2. מעתיק commit ספציפי לענף הנוכחי
    3. ממזג ענף שלם
    4. מוחק commit
    הצגת התשובה

    תשובה ב. שימושי להעביר תיקון באג אחד לענף אחר.