ראיתי השבוע חבר מקליד את הפקודה הבאה בגיט כדי לצאת ממצב מביך:
$ git reset --hard origin/master
בואו נראה מה היא עושה כדי להבין אם היא יכולה לעזור גם לכם.
מתחילים בתיעוד של גיט. יש לגיט ריסט שלושה מצבי פעולה:
git reset [-q] [<tree-ish>] [--] <paths>...
git reset (--patch | -p) [<tree-ish>] [--] [<paths>...]
git reset [--soft | --mixed [-N] | --hard | --merge | --keep] [-q] [<comm
it>]
הסיפור שלנו מתמקד במצב השלישי, כלומר הפעולה הזאת:
In the third form, set the current branch head (HEAD) to
<commit>, optionally modifying index and working tree to match.
לכן הדבר הראשון שריסט יעשה הוא לשנות את HEAD כך שיצביע על הקומיט שעובר בפרמטר האחרון. הקומיט הזה במקרה שלנו הוא origin/master
שזה אומר הקומיט שאנחנו חושבים שהשרת קורא לו master. זה אומר שאם עשינו כבר קומיטים אצלנו ב master אנחנו הולכים לחזור לנקודה לפני הקומיטים שלנו. מצד שני פקודת reset לא פונה לשרת לכן אם מישהו אחר עשה push לשרת אנחנו לא נדע מזה. אנחנו נלך למקום ש origin/master היה בו בפעם האחרונה שפנינו לשרת.
אפשר לראות את הנקודה הזאת עם:
$ git log -1 origin/master
או אם מה שמעניין אתכם זה רק ה Commit Hash תוכלו להפעיל:
$ git rev-parse origin/master
a08935913801409ef7437ba9038d4a0580f1f6c5
ועם פקודה דומה נוכל לגלות אם ה master שלנו כבר התקדם מהקומיט הזה או שהוא עדיין שם:
$ git rev-parse master
a08935913801409ef7437ba9038d4a0580f1f6c5
דרך אחרת היא פשוט להפעיל status. אם ה master שלכם לא תואם ל origin/master תקבלו על זה הודעה בשורה השניה של הפלט. במקרה שלי הם תואמים אז יש לנו:
$ git status
On branch master
Your branch is up to date with 'origin/master'.
nothing to commit, working tree clean
בחזרה ל reset - אז הדבר הראשון שיקרה זה ש HEAD יעבור להצביע על הקומיט שנקרא origin/master
. הדבר השני ש reset עושה זה לעדכן את הקבצים בתיקיית העבודה. המתג --hard
אומר:
Resets the index and working tree. Any changes to tracked files in the working tree
since <commit> are discarded.
לכן הפקודה תנקה את כל ה Staging Area ותעתיק את הקבצים מהקומיט אליו אנחנו חוזרים ל Staging Area. אחרי זה היא תעשה את אותו דבר עם הקבצים בתיקיית העבודה שלנו. נשים לב שמדובר רק על שינויים בקבצים במעקב בתיקיית העבודה, לכן קבצים שיש לכם בתיקיית העבודה שלא נמצאים בריפוזיטורי לא יושפעו מהפקודה (בשביל למחוק אותם תרצו לקרוא על git clean
, אבל זה סיפור לפוסט אחר).
לסיכום הפקודה git reset --hard origin/master
עושה את הדברים הבאים:
היא בודקת מה מזהה הקומיט של הענף origin/master
.
היא מזיזה את הענף הנוכחי כך שיצביע גם הוא לאותו קומיט. יחד איתו יזוז גם ה HEAD.
היא מאפסת את כל הקבצים ב Staging Area ולוקחת את הגירסא מהריפוזיטורי.
היא מעתיקה מהריפוזיטורי לתיקיית העבודה את כל הקבצים שהגירסא שלהם בתיקיית העבודה שונה מזו ששמורה בריפוזיטורי (אבל מתעלמת מקבצים בתיקייה שלא שמורים בריפוזיטורי).
אפשר להשתמש בפקודה כדי "לאפס" את הקומיטים שעשיתם ואת השינויים שעדיין לא עשיתם להם קומיט בתיקיית העבודה, ולחזור לגירסא שהיתה לנו בריפוזיטורי.
וקטנה לסיום- אם הפעלתם את git reset --hard origin/master
בטעות ופתאום נעלמו לכם הקומיטים שעשיתם, אתם תמיד יכולים לגשת ל git reflog
כדי למצוא את הקומיטים האבודים. אחרי שמצאתם את הקומיט ש master
הצביע עליו קודם, תוכלו להשתמש ב git reset
נוסף כדי לחזור אליו.