ביטול שינויים

אחת היכולות החשובות ביותר ב-git: לחזור אחורה. הקובץ הזה מכסה איך לבטל שינויים בכל אחת מהרמות - working directory, staging area ו-commits.

ביטול שינויים ב-Working Directory

מצב: ערכת קובץ אבל לא הוספת אותו ל-staging, ואתם רוצים להחזיר אותו למצב המקורי.

git restore file.js              # ביטול שינויים בקובץ ספציפי
git restore .                    # ביטול כל השינויים בתיקייה הנוכחית
git checkout -- file.js          # תחביר ישן (עדיין עובד)

⚠️ אזהרה: הפעולה הזו מוחקת את השינויים שלא נשמרו - בלי אפשרות שחזור.

הסרה מ-Staging Area

מצב: עשיתם git add בטעות לקובץ שלא רציתם לכלול ב-commit הבא.

git restore --staged file.js     # מסיר מ-staging, השינויים נשארים בקובץ
git reset HEAD file.js           # תחביר ישן

הקובץ חוזר למצב Modified - השינויים בו נשמרים, אבל הוא לא ב-staging.

ביטול commits

יש שתי גישות עיקריות לביטול commits: reset ו-revert. ההבדל ביניהן קריטי.

git reset - מחיקת commits מההיסטוריה

reset משנה היסטוריה - "מחזיר את הזמן אחורה". בא בשלוש רמות:

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

⚠️ --hard הוא הרסני: הוא מוחק את כל השינויים שלא נשמרו ב-commits. השתמשו רק כשאתם בטוחים לחלוטין.

דוגמאות שימוש

# "ביטלתי את ה-commit האחרון אבל אני רוצה לערוך אותו"
git reset --soft HEAD~1
# עכשיו השינויים ב-staging - ערוך וקצור commit חדש

# "סיימתי עם ה-commit הזה, אני רוצה למחוק אותו לגמרי"
git reset --hard HEAD~1

git revert - יצירת commit הפוך

revert לא משנה היסטוריה - הוא יוצר commit חדש שמבטל commit קיים. זו הדרך הבטוחה לבטל commit שכבר נשלח לשרת המרוחק (כי הוא לא דורס היסטוריה).

git revert a3f5c2d           # יוצר commit חדש שמבטל את a3f5c2d
git revert HEAD              # מבטל את ה-commit האחרון
git revert HEAD~1            # מבטל את ה-commit הקודם (לא האחרון)

reset לעומת revert - מתי להשתמש במה?

מצב להשתמש ב
ה-commit מקומי, לא נשלח לשרת reset
ה-commit כבר נשלח לשרת המרוחק revert
רוצים למחוק את ההיסטוריה reset --hard
רוצים לבטל את האפקט אבל לשמור היסטוריה revert

🚫 כלל ברזל: אם ה-commit כבר נשלח לשרת ומישהו אחר משתמש ב-branch הזה - לעולם אל תעשו reset. השתמשו ב-revert.

שחזור קובץ מ-commit ישן

git checkout HEAD -- file.js      # שחזור קובץ למצבו ב-HEAD
git checkout HEAD~3 -- file.js    # שחזור קובץ למצבו לפני 3 commits
git restore --source=HEAD~3 file.js   # תחביר חדש

שחזור commit "אבוד" עם reflog

הזכרנו בשיעור 6 שיש את git reflog שמציג את כל הפעולות שעשיתם. אם בטעות עשיתם reset --hard ואיבדתם commits:

git reflog
# מחפשים את ה-SHA של ה-commit האבוד
git reset --hard a3f5c2d

זו הדרך לחזור גם מטעויות שנראות בלתי הפיכות.

תיקון ה-commit האחרון

מצב: עשיתם commit ושכחתם להוסיף קובץ, או טעיתם בהודעה.

# הוספת קבצים שנשכחו ל-commit האחרון
git add forgotten-file.js
git commit --amend --no-edit

# שינוי הודעת ה-commit האחרון
git commit --amend -m "Better message"

⚠️ --amend משנה את ה-SHA של ה-commit. אם כבר עשיתם push - תצטרכו force push שזה מסוכן ל-branches משותפים.

בדקו את עצמכם

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

  1. איך מבטלים שינוי בקובץ שעוד לא נכנס ל-staging?

    1. git commit
    2. git push
    3. git log
    4. git restore file
    הצגת התשובה

    תשובה ד. git restore מחזיר את הקובץ למצב של ה-commit האחרון.

  2. איך מתקנים את הודעת ה-commit האחרון (שעוד לא נדחף)?

    1. git reset --hard
    2. git revert
    3. אי אפשר
    4. git commit --amend
    הצגת התשובה

    תשובה ד. amend מחליף את ה-commit האחרון. לא עושים את זה על commit שכבר נדחף.