reset ו-revert

שתי הפקודות הללו "מבטלות" שינויים, אבל בדרכים שונות מאוד. הבחנה בין השתיים היא קריטית.

ההבדל המרכזי

reset revert
משנה היסטוריה ✅ ❌
יוצר commit חדש ❌ ✅
בטוח ל-branches משותפים ❌ ✅
ניתן לשחזור קשה קל

git reset

reset "מחזיר את הזמן אחורה" - הוא מזיז את ה-branch למצביע על commit ישן יותר. ה-commits שהיו אחריו "נעלמים" (פיזית הם עדיין במאגר, אבל לא מקושרים).

שלוש רמות

git reset --soft HEAD~1     # רק זז אחורה, השינויים נשארים ב-staging
git reset --mixed HEAD~1    # זז אחורה + מנקה staging (ברירת מחדל)
git reset --hard HEAD~1     # זז אחורה + מנקה staging + מנקה working dir

--soft

לפני:
working dir:  כל השינויים
staging:      כל השינויים
HEAD:         commit C  (אחרון)

git reset --soft HEAD~1

אחרי:
working dir:  כל השינויים
staging:      כל השינויים
HEAD:         commit B

שימוש: ביטלת commit, השינויים מוכנים לקצור ל-commit חדש.

--mixed (ברירת מחדל)

אחרי:
working dir:  כל השינויים
staging:      ריק
HEAD:         commit B

שימוש: ביטלת commit, השינויים בקבצים אבל צריך לבחור מחדש מה ל-stage.

--hard

אחרי:
working dir:  ריק (חזר למצב של commit B)
staging:      ריק
HEAD:         commit B

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

🚫 --hard הוא הרסני! השתמשו רק כשאתם בטוחים. אין דרך פשוטה לחזור.

דוגמאות

# ביטול 3 commits אחרונים, השארת השינויים בקבצים
git reset --mixed HEAD~3

# חזרה לגרסה ישנה של main, מוחק הכל שאחרי
git reset --hard a3f5c2d

# הסרת קובץ מ-staging (השינויים נשארים בקובץ)
git reset HEAD file.js

git revert

revert יוצר commit חדש שמבטל את האפקט של commit ישן. ההיסטוריה לא משתנה - ה-commit הישן עדיין שם, ויש אחריו commit חדש שהוא ההפך שלו.

git revert a3f5c2d                # יוצר commit חדש שמבטל את a3f5c2d
git revert HEAD                   # מבטל את ה-commit האחרון
git revert HEAD~3..HEAD           # מבטל 3 commits אחרונים
git revert -n a3f5c2d             # רק staging, בלי commit אוטומטי

דוגמה

לפני revert:
main:    A───B───C───D───E

git revert C

אחרי:
main:    A───B───C───D───E───C'  ← C' מבטל את C

C' הוא commit חדש שהשינויים שלו הם בדיוק ההפך של C.

מתי להשתמש במה?

השתמשו ב-reset כש:

  • ה-commit עדיין מקומי, לא נדחף לשרת
  • אתם רוצים למחוק עבודה שלא צריכה להופיע בהיסטוריה
  • אתם צריכים לחזור אחורה כדי להתחיל מחדש

השתמשו ב-revert כש:

  • ה-commit כבר נדחף לשרת
  • ה-branch משותף עם מפתחים אחרים
  • אתם רוצים לתעד שהיה כאן באג ותיקנו אותו

הזרימה המעשית

# מצב: עשית commit עם באג ועדיין לא דחפת
git reset --soft HEAD~1
# מתקנים, עושים commit חדש

# מצב: עשית commit עם באג וכבר דחפת
git revert HEAD
git push

reset לקובץ ספציפי

git reset HEAD file.js              # מסיר מ-staging
git restore --staged file.js        # תחביר חדש - אותו דבר

דוגמה מלאה: ביטול pull לא רצוי

# עשית git pull וקיבלת שינויים שלא רצית
git reflog
# a3f5c2d HEAD@{0}: pull: Fast-forward
# b8e7f1a HEAD@{1}: commit: My last commit before pull
# ...

# חוזרים למצב לפני ה-pull
git reset --hard b8e7f1a

אזהרה גדולה לסיום

🚫 לעולם אל תעשו git reset --hard על branch משותף שכבר נדחף לשרת.

אם אתם צריכים לבטל commits ב-branch שכבר נדחף - השתמשו ב-revert. תמיד.

בדקו את עצמכם

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

  1. מה ההבדל בין reset ל-revert?

    1. revert יוצר commit חדש שמבטל, reset מזיז אחורה ומוחק מההיסטוריה
    2. reset בטוח לענף משותף
    3. revert מוחק קבצים
    4. אין הבדל
    הצגת התשובה

    תשובה א. בענף משותף משתמשים תמיד ב-revert.

  2. מה מסוכן ב-git reset --hard?

    1. כלום
    2. הוא איטי
    3. הוא מוחק שינויים שלא נשמרו ב-commit, בלי דרך פשוטה לשחזר
    4. הוא דוחף לשרת
    הצגת התשובה

    תשובה ג. לפני --hard כדאי git stash.