פוסט
Git מאפס לגיבור: לבטל טעויות
חלק 3 במדריך ל-Git: איך מצביעים על commit (HEAD~1, HEAD^2, HEAD@{2}), מה זה detached HEAD, והביטול הנכון לכל טעות: restore, amend, reset, revert ו-reflog.
כל ביטול ב-Git מצביע על commit כלשהו, ולכן החלק הזה מתחיל באיך מצביעים על commit, עם ההיסטוריה של ספר המתכונים מחלק 2.
איך מצביעים על commits
בכל מקום ש-Git מבקש commit, אפשר לתת לו כל אחד מאלה:
| כותבים | המשמעות |
|---|---|
9c1d4e2 |
commit לפי ה-hash (הקצר) שלו |
main, pizza |
ה-commit שענף מצביע עליו |
v1.0 |
ה-commit שתגית מצביעה עליו |
HEAD |
ה-commit שאנחנו עליו |
HEAD~1 (או HEAD^) |
commit אחד לפני HEAD, ההורה שלו |
HEAD~3 |
שלושה commits אחורה לאורך השרשרת |
HEAD^2 |
ההורה השני של commit מיזוג |
HEAD@{2} |
איפה HEAD היה לפני שתי תזוזות (מה-reflog) |
כך ש-git diff HEAD~2 HEAD משווה בין עכשיו לבין לפני שני commits, ו-git show main~1 מציגה את ה-commit שלפני הקצה של main.
Detached HEAD. בדרך כלל HEAD מצביע על ענף. עוברים ישירות ל-commit, למשל עם git switch --detach 3f2a1b9, ו-HEAD מצביע ישר עליו. זה מקום טוב להסתכל על קוד ישן, אבל commits שנעשים שם לא שייכים לאף ענף וקל לאבד אותם. כדי לשמור אותם: git switch -c keep-this. כדי לצאת: git switch main.
ביטול טעויות
git checkout הישנה עשתה את רוב המשימות האלה ובלבלה את כולם. מאז Git 2.23, git switch עוברת בין ענפים ו-git restore מטפלת בקבצים. הכלי הנכון תלוי באיפה הטעות.
ערכנו קובץ ורוצים בחזרה את הגרסה מה-commit האחרון:
git restore pasta.md # ⚠️ זורקת את העריכות בקובץ הזה
עם --source=<commit> מקבלים את הקובץ כפי שהיה ב-commit ישן יותר.
הכנסנו ל-staging קובץ לא נכון:
git restore --staged todo.md
טעות בהודעה של ה-commit האחרון, או ששכחנו קובץ:
git add forgotten.md
git commit --amend # מחליפה את ה-commit האחרון
רוצים לבטל את ה-commit האחרון אבל לשמור את העבודה. git reset מזיזה את תווית הענף אחורה. שלושה מצבים קובעים מה קורה לשינויים שהיו באותו commit:
git reset --soft HEAD~1 # מבטלת את ה-commit, השינויים נשארים ב-staging
git reset HEAD~1 # אותו דבר, השינויים נשארים מחוץ ל-staging (--mixed היא ברירת המחדל)
git reset --hard HEAD~1 # ⚠️ מבטלת את ה-commit ומוחקת את השינויים
ה-commit כבר נדחף. לא משכתבים היסטוריה משותפת. מוסיפים commit חדש שמבטל את הישן:
git revert 9c1d4e2
כלל אצבע: commits שקיימים רק במחשב שלנו מותר לשכתב (reset, amend, rebase); אם ייתכן שלמישהו אחר יש אותם, משתמשים ב-revert.
התחלנו לעבוד על main בטעות. git switch -c new-branch יוצרת ענף במקום שבו אנחנו, והשינויים שעוד לא נכנסו ל-commit באים איתנו.
נדמה לנו שאיבדנו משהו. כמעט שום דבר לא הולך לאיבוד. git reflog מציגה כל מקום ש-HEAD היה בו, גם אחרי reset קשיח, rebase או מחיקת ענף:
git reflog
git switch -c rescue 9c1d4e2 # שמים ענף על ה-commit שחשבנו שנעלם