כשסוכן קוד עורך את הפרויקט שלכם, אתם צריכים לראות מה השתנה, ולשמור גרסה שאפשר לחזור אליה. Git נותן לנו דרך לעשות את שני הדברים. קודם נסביר איך Git מפריד בין הקבצים שאתם עורכים לבין הגרסאות שתיעדתם. אחר כך, בעזרת משחק קטן, נקרא את השינויים של הסוכן, נבדוק אותם, ונשמור אותם כקומיט. נשחזר גם קובץ אחרי עריכה לא רצויה.
נניח שהפרויקט שלכם עובד, ואתם מבקשים מסוכן להוסיף פיצ'ר. הסוכן עורך כמה קבצים ושומר אותם. עכשיו הקבצים האלה מכילים את השינויים שלו.
שמירה בעורך כותבת לדיסק את התוכן הנוכחי. אבל היא לא שומרת היסטוריה של גרסאות קודמות. אם הפיצ'ר החדש שובר משהו, אנחנו צריכים את התוכן הקודם, כדי להשוות אליו או לחזור אליו.
Git הוא מערכת לניהול גרסאות. כלומר, הוא שומר היסטוריה של גרסאות הפרויקט שאנחנו בוחרים לתעד.
בעזרת ההיסטוריה הזו אפשר להשוות את הקבצים הנוכחיים לגרסה קודמת, לקרוא את השורות שהשתנו, ולשחזר תוכן שתיעדנו. זה שימושי במיוחד כשעובדים עם סוכן, כי הוא יכול לשנות הרבה קבצים לפני שקראנו אפילו אחד מהם.
נתחיל בקבצים שעל המחשב שלכם. קובצי הפרויקט שאפשר לפתוח, לערוך ולהריץ נקראים עץ העבודה, ה-working tree. הם כוללים את קוד המקור ועוד קבצים שהתוכנית שלכם צריכה.
כששומרים עריכה, או כשהסוכן כותב קובץ, עץ העבודה משתנה. זו העבודה הנוכחית, כולל שינויים שעוד לא עברתם עליהם.
קומיט הוא גרסה מתועדת של הקבצים ש-Git עוקב אחריהם. קבצים במעקב הם הקבצים שהכנסנו לניהול הגרסאות של Git. Git לא כולל אוטומטית את כל הקבצים שבתיקייה.
אפשר לחשוב על קומיט כעל תמונת מצב של הקבצים האלה יחד. אחרי שעושים קומיט, אפשר להמשיך לערוך את עץ העבודה. העריכות האלה לא משנות את הקומיט שכבר עשינו.
Git שומר את הקומיטים במאגר, repository, שלרוב מקצרים ל-repo. שם Git מחזיק את הגרסאות המתועדות ואת ההיסטוריה שלהן. בשיחה יומיומית, אומרים repo גם כשמתכוונים לפרויקט יחד עם ההיסטוריה הזו.
כל עיגול כאן מייצג קומיט אחד. קומיט חדש מצביע אחורה על הקומיט שהוא מבוסס עליו, כך שאפשר לעקוב איך הפרויקט התפתח. המאגר ועץ העבודה נמצאים על המחשב שלנו. כשעושים קומיט, הוא לא עולה לשום מקום.
לפני שעושים קומיט, בוחרים אילו שינויים ייכנסו אליו. ב-Git קוראים לזה staging. אזור ה-staging מחזיק את גרסאות הקבצים שהוכנו לקומיט הבא.
הפקודה git add מכניסה את התוכן הנוכחי של קובץ לגרסה המוכנה. ואז git commit מתעד את הגרסה המוכנה במאגר. גם קבצים במעקב שלא השתנו נשארים חלק מתמונת המצב. הבחירה בשינויים לא אומרת שכל שאר הקבצים נעלמים.
ההפרדה הזו מאפשרת לנו לשמור יחידת עבודה אחת מגובשת, כמו פיצ'ר והטסט שלו, ולהשאיר בחוץ עריכות שלא הסתיימו.
הסוכן יכול לכתוב ולהריץ את הפקודות האלה בשבילכם. אתם צריכים להבין מה כל פקודה עושה ולקרוא את התוצאה שלה, כדי לדעת אם הסוכן עשה את מה שרציתם.
בדוגמה, כל פקודה נדלקת כשהיא רצה, ואז נסביר אותה. התחביר המלא נמצא בתיעוד של Git, כשתצטרכו אותו.
עכשיו ניישם את זה על פרויקט. זה משחק קטן שרץ בדפדפן. החללית יורה על החייזרים, והניקוד עולה בכל פגיעה.
בתיקייה מימין נמצאים הקבצים שמרכיבים את המשחק. הקובץ index.html הוא דף האינטרנט. הקובץ game.js שולט בתנועה, בפגיעות ובניקוד. הקובץ theme.css שולט בצבעים ובמראה.
המשחק כבר עובד, והפרויקט הזה כבר משתמש ב-Git. אנחנו רוצים שהסוכן יוסיף פיצ'ר אחד: לחיצה על P תשהה את המשחק ואת הניקוד, ולחיצה נוספת על P תחזיר אותם לפעולה.
לפני שמוסיפים את ההשהיה, נבקש מהסוכן לבדוק את המשחק הנוכחי ולתעד את העבודה שיש לנו עד עכשיו. כך תהיה לנו גרסת התחלה להשוות אליה אחרי שהסוכן יבצע את השינויים שלו.
כאן הסוכן כבר בדק את המשחק והכניס את העבודה הנוכחית ל-staging. את הפקודה שמכניסה ל-staging נראה בפירוט כשנשמור את פיצ'ר ההשהיה.
הסוכן מריץ git commit כדי לתעד את הגרסה המוכנה הזו. גרסת ההתחלה של המשחק שמורה עכשיו במאגר כקומיט. קובצי העבודה עדיין כאן, והסוכן יכול לערוך אותם.
המילים Working game הן הודעת הקומיט. האפשרות -m מעבירה את ההודעה הזו ל-git commit. הודעה טובה מתארת את העבודה שמתועדת, כך שמי שקורא את ההיסטוריה יוכל לזהות אותה.
Git גם נותן לקומיט מזהה. המזהה המקוצר שמופיע כאן מפנה בדיוק לגרסה המתועדת הזו. נשתמש בו בפקודה שמשווה את השינויים של הסוכן לנקודת ההתחלה שלנו. ההודעה היא תיאור שאנחנו בוחרים. המזהה הוא הדרך לומר ל-Git בדיוק לאיזה קומיט אנחנו מתכוונים.
הפקודה git status מדווחת על מצב העבודה הנוכחית: אילו שינויים ב-staging, אילו לא, ואילו קבצים חדשים Git עוד לא עוקב אחריהם. כאן כתוב working tree clean. כל הקבצים שבמעקב זהים לקומיט האחרון, אז אפשר להתחיל את פיצ'ר ההשהיה מגרסה ידועה.
נבקש מהסוכן שהמקש P ישהה את המשחק ויחזיר אותו לפעולה, ושהניקוד לא ישתנה בזמן ההשהיה. לפני שנעשה קומיט למשהו, נסתכל על השינויים בעצמנו.
משמאל המשחק רץ, החייזרים מתקדמים והניקוד עולה. מימין הוא מושהה, והניקוד נשאר במקום.
הסוכן מריץ עכשיו git status בצורה המקוצרת שלו, שמציגה את הקבצים ששונו ואת הקבצים החדשים, אחד בכל שורה. קובץ הלוגיקה של המשחק מסומן ב-M, כלומר modified, שונה. הסוכן גם כתב קובץ טסט, קוד שבודק את ההתנהגות של המשחק באופן אוטומטי. שני סימני השאלה שלו אומרים ש-Git עוד לא עוקב אחריו. ב-Git קוראים לזה untracked, שלא במעקב.
נצטרך לבדוק את הקובץ החדש, וגם את השינויים בקוד הקיים. הקומיט השמור עצמו לא השתנה.
status אומר לנו אילו קבצים השתנו. כדי לראות מה השתנה בתוך קובץ, קוראים diff. diff הוא השוואה, שורה אחר שורה, בין שתי גרסאות.
בסקירה הזו, שתי הגרסאות הן קומיט ההתחלה שלנו והקבצים אחרי העריכה של הסוכן. אנחנו רוצים לבדוק אם השינויים מממשים את ההשהיה שביקשנו.
את ההשוואה הזו אנחנו מריצים בעצמנו. נקליד git diff עם המזהה של נקודת השמירה שלנו, והפקודה תדפיס כל שורה שבה הקבצים של עכשיו שונים מאותו קומיט. אפשר לבקש diff מהסוכן, אבל קראו אותו בעצמכם, בטרמינל שלכם.
הריצו את זה מתיקיית הפרויקט שלכם, עם המזהה של קומיט ההתחלה שלכם. המזהה שבשקף שייך לדוגמה שלנו.
זה קטע מהלוגיקה של המשחק. מינוס מסמן שורה שהוסרה, ופלוס מסמן שורה שנוספה.
שתי השורות ששונו הן בעצם שורה אחת שהוחלפה בחדשה. השורה הישנה קידמה את המשחק בכל עדכון. השורה החדשה מקדמת אותו רק כשההשהיה כבויה.
שימו לב לשורה שמתחתיהן, זו שמציירת את המסך. היא לא השתנתה, וכך צריך להיות. צריך לצייר את המשחק על המסך גם כשהוא מושהה.
קובץ הטסט החדש לא נמצא ב-diff הזה, כי Git משווה רק קבצים שהוא עוקב אחריהם. פתחו אותו בנפרד.
הוא בודק שהניקוד מתקדם בזמן שהמשחק רץ, ושהוא לא מתקדם בזמן ההשהיה. זה תואם את הבקשה.
לפני שמאשרים את הפיצ'ר, בדקו שהמשחק עובד ושהפיצ'ר מוצא חן בעיניכם. לחצו על P ובדקו שהמשחק והניקוד מפסיקים להתקדם. ואז לחצו שוב על P ובדקו שהמשחק ממשיך.
הסוכן מריץ עכשיו node --test, שמריץ את הטסטים של הפרויקט, כולל הטסט החדש.
כל ארבעת הטסטים עוברים. אם משהו היה לא תקין, היינו מבקשים מהסוכן לתקן אותו לפני שעושים לפיצ'ר קומיט.
הפיצ'ר עובד, ועברנו על הקוד שלו ועל הטסט שלו. נרצה לתעד את שניהם יחד, אז נבקש מהסוכן לעשות להם קומיט.
הסוכן מריץ git add עם השמות של קובץ המשחק ושל קובץ הטסט החדש. זה מכניס את התוכן הנוכחי שלהם ל-staging לקראת הקומיט הבא. הוספת הטסט החדש גם מכניסה אותו למעקב של Git. עוד לא עשינו קומיט לשום דבר.
הפקודה git add מכניסה ל-staging את תוכן הקובץ כפי שהוא ברגע שהיא רצה. נניח שעורכים שוב את קובץ המשחק אחרי שהוא נכנס ל-staging. בעץ העבודה יש עכשיו את העריכה החדשה, אבל בגרסה שב-staging עדיין נמצא התוכן הקודם.
כדי לכלול את העריכה החדשה, צריך להריץ שוב git add. בדוגמה שלנו, אנחנו מוכנים לעשות קומיט לגרסאות שעברנו עליהן עכשיו.
הסוכן מריץ עכשיו git commit עם ההודעה Add pause control. Git מתעד את השינויים שב-staging בתמונת מצב חדשה, ושומר בה גם את הקבצים שבמעקב שלא השתנו.
בהיסטוריה, הקומיט החדש בא אחרי Working game. שתי הגרסאות נשארות זמינות. כשהפיצ'ר והטסט שלו נשמרים יחד, ברור מה הקומיט הזה הוסיף.
יש קבצים בתיקיית הפרויקט שצריכים להישאר מחוץ להיסטוריית הגרסאות שלו. כאן, התיקייה dist מכילה פלט בנייה, שאפשר ליצור מחדש מקובצי המקור. הקובץ .env מחזיק הגדרות מקומיות, שיכולות לכלול סודות.
הקובץ .gitignore מפרט נתיבים ש-Git צריך להשאיר מחוץ למעקב. התוכן שלו מוצג משמאל. הרצה רגילה של git add משאירה בחוץ את הקבצים שברשימה הזו.
הרשימה הזו משפיעה רק על קבצים ש-Git עוד לא עוקב אחריהם. אם מוסיפים ל-.gitignore שם של קובץ שכבר במעקב, זה לא מוציא אותו מקומיט, ו-Git ממשיך לעקוב אחריו.
נניח שהעריכה הבאה שוברת את ההשהיה. עוד לא עשינו לה קומיט, ואנחנו לא רוצים לשמור אותה.
ה-diff מראה שהתנאי הוסר, והטסט של ההשהיה נכשל שוב.
נבקש מהסוכן לשחזר את קובץ המשחק מהקומיט של ההשהיה. הוא מבהיר שזה יחליף את העריכות הנוכחיות באותו קובץ, וזה בדיוק מה שאנחנו רוצים.
הסוכן מריץ עכשיו git restore, עם מקור ויעד. המקור הוא המזהה של קומיט ההשהיה, והיעד הוא קובץ המשחק. זה מחזיר לעץ העבודה את הגרסה של הקובץ הזה, כפי שהיא באותו קומיט.
הטסט של ההשהיה עובר שוב, ועץ העבודה נקי. הקומיטים עצמם לא השתנו.
כאן שחזרנו קובץ אחד שבמעקב, מתוך קומיט שעשינו. במצבי שחזור אחרים, אמרו לסוכן מה חייב להישמר, ובדקו שאתם מבינים את הפקודה המוצעת לפני שהיא רצה. Git לא יכול לשחזר עבודה שהוא אף פעם לא שמר.
עכשיו אנחנו יכולים לתת לסוכן לעבוד מנקודת התחלה מתועדת, לבדוק את השינויים שלו, ולשמור את הפיצ'ר שעברנו עליו כקומיט נפרד. ואם עריכה מאוחרת יותר פוגעת בקובץ, יש לנו גרסה שמורה לחזור אליה.
הסוכן יכול לעזור עם התחביר של הפקודות. התפקיד שלנו הוא להבין איזו גרסה משווים או מתעדים, ולהחליט אם השינויים שייכים לפרויקט.
נתראה בסרטון הבא. שם נמשיך ללמוד עוד קצת על Git.