
- Published on
איך נכון לעבוד בבראנצ' הפרטי שלכם?
- Authors
- Name
- אביב אביטן
- in/avivavitan

נתחיל מזה שיש בGIT בעיני שתי רמות: פרויקטואלית ואישית.
ברמה הפרויקטאלית יש שתי שיטות מרכזיות, TRUNK BASED DEVELOPMENT ו-GITFLOW. הפוסט הזה לא נוגע אליהם כלל.
אנחנו נתרכז ברמה האישית - לא משנה באיזו שיטה פרוייקטיאלית נעבוד, בכל השיטות המוזכרות אנחנו נדרשים בימים כתיקונם פשוט למזג קוד מהבראנצ' האישי שלנו לבראנצ' כללי יותר (נניח מאסטר לשם פשטות), דרך PULL REQUEST.
בראנצ'ים אישיים אמורים להיות קצרי מועד. ככל שהזמן עובר אנו ניצבים בפני שתי אפשרויות לשאלה כיצד נתיישר לשינויים שקרו במאסטר, אותם נרצה להביא אותם לבראנצ' פיתוח שלנו. אני אכנה את שתי האפשרויות למען הפשטות: שיטת ה-REBASE ושיטת ה-MERGE.
REBASE
בשיטת ה-REBASE - יישור לשינויים מתרחש כאילו יצרנו הבראנצ' ברגע זה מתוך המאסטר. זו מתרחשת ע"י הפעולה GIT REBASE ORIGIN MASTER. בסופו הבראנצ' יכיל רק קומיטים של השינוי שלנו בלבד (קרי ללא MERGE COMMITS). כלומר ככל שהמאסטר מתקדם, אנחנו ניקח את כל קומיטים שיצרנו ונעביר אותם על בסיס ה-HEAD של המאסטר המעודכן. בשיטה זו אנחנו נמנעים מ-MERGE COMMITS שעליהם נפרט בהמשך מדוע ראוי להימנע מהם.
MERGE
שיטת ה-MERGE היא כנראה השיטה הנפוצה ביותר. היא מתרחשת ע"י ביצוע הפעולה GIT MERGE ORIGIN MASTER. פעולה זאת תביא לבראנצ' פיתוח שלנו את כל שינויי הקוד מהמאסטר (אלו שלא נכללו בבראנצ' שלנו) אבל נקבל אותם כקומיט מיוחד שאורז את כל השינויים האלה לתוך הבראנצ' שלנו. אותו הקומיט שנכנס לבראנצ' שלנו הוא ה-MERGE COMMIT שהזכרנו קודם והייחוד שלו הוא בשני דברים:
- הוא יכיל את כל הקוד מהמאסטר, מכלל הקומיטים החדשים + תיקוני הקונפליקטים שנעשו בזמן ה-merge
- חשוב מכך, בעל הצבעה לשתי אבות ולא לאחד (הצבעת לקומיט האחרון בברנאצ' הפרטי שלנו והצבעה לקומיט האחרון בראנצ' מאסטר).
שתי השיטות מקובלות מאוד בתעשייה. למעשה לשתי השיטות יש חסידים מושבעים. אבל צריך לעמוד על ההבדלים ונמנה שלושה עיקריים ונציג שיטת עבודה שנהנת מהיתרונות והחסרונות של כל אחת.
הבדל 1: תהליך יישור למאסטר

גם אם "הסיפור" של הקומיטים נשמר, ייתכן שעדיין חסר קוד. נניח למשל, שבשינוי שלנו הוספנו לוגים לפונקציות במודול. ה-REBASE הכניס קוד חדש של המודול, אבל לא כולל הלוגים אותם הוספנו בבראנצ' הפרטי שלנו. במקרה הזה ליצור קומיט חדש עם התיקון ואז להשתמש ב-REBASE אינטראקטיבי כדי להכניס את הלוגים ולמזג את הקומיט החדש בקומיט הישן המתאים. להלן איך נראה חלון של REBASE אינטרקטיבי: רואים רשימת קומיטים, שאפשר לשנות את הסדר שלהם ולמזג קומיטים ע"י השימוש במילה השמורה FIXUP או SQUASH במקום PICK.

כעת נעבור לשיטת ה-MERGE. בשיטה זו התחלנו עם N קומיטים ונסיים עם N+1 לכל יישור כאשר הקומיט ה+1 הוא ה-MERGE COMMIT. ועכשיו נניח בדומה למקרה הקודם, בהוספת הלוגים, שיש שינוי בקוד החדש שצריך להיות כחלק מקומיט ישן יותר. בדומה, נצטרך ליצור קומיט חדש שמוסיף את התיקון, אך אחרי שנעשה את השינוי לא נוכל למזג אותו לקומיט הישן יותר באמצעות GIT REBASE אינטרקטיבי.
מדוע? ברגע שנכנס MERGE COMMIT לברנאצ' שלך - אי אפשר לשנות יותר את העץ ו\או את הסידור קומיטים של הבראנצ'. ייתכן גם שאותו שינוי קוד היה נעשה כחלק מפתירת קונפליקטים בזמן היישור. במקרה זה הקומיט הישן שלנו עדיין לא יכיל את הלוגיקה הנוספת שנכנסה ב-MERGE COMMIT עצמו ולא בקומיט המתאים לכך. חוסר האפשרות לערוך קומיטים לפני ה-MERGE COMMIT הוא חסרון שפוגע בשליטה שלנו על מבנה הבראנצ' הפרטי שלנו.

הבדל 2: ניהול קונפליקטים
בשיטת ה-REBASE, כל קומיט בברנאצ' שלנו מוכל לפי סדר על ה-MASTER החדש. כאשר יש קונפליקט, צריך לפתור אותו כאילו אנו כותבים את הקומיט הנוכחי, בהתעלמות מהמצב הסופי של הקוד. אם למשל יש קומיט C1 ששינה קטע קוד מסויים, אך קיים גם קומיט C2 מאוחר יותר ששינה את אותו קטע קוד, עלינו להיות מודעים לכך שאנחנו צריכים לשנות לפי C1 ולא לפי C2. לטעויות אין מקום, כל טעות ביישור תוביל לעוד ועוד קונפליקטים בקומיטים הבאים ותגרום לתהליך היישור להיות לא ישים. דבר זה עלול להקשות מאד על התיישרות ל-MASTER.
בשיטת ה-MERGE, אין לנו שיקול כזה. בזמן קונפליקט אנחנו מחפשים את המצב הסופי הראוי של הקוד. קרי, לוקחים מ-THEIRS את הקוד "החדש" ומוסיפים אליו את הקוד שלנו. בסיום הקונפליקטים יווצר לנו ה-MERGE COMMIT בראש הבראנצ' שלנו שיכיל את השינויים. דבר זה יותר אינטואיטיבי למפתח. בנוסף יש סלחנות כלפי טעויות: אפשר ליצור קומיט חדש שמתקן את הטעות שנעשה בזמן קונפליקט.
בשיטה ה-REBASE אנחנו נוכל ליהנות מיתרון ההשוואה של הקונפליקט רק למצב הקוד הסופי - רק אם טרום היישור איחדנו את כל הקומיטים לקומיט יחיד. דבר שמתרחש רק כאשר סיימנו את השינוי שלנו ואנחנו לפני מיזוגו למאסטר.
הבדל 3: איך ממזגים את השינוי בחזרה למאסטר
בשיטת ה-REBASE - כאשר נסיים את העבודה נעשו REBASE אינטרקטיבי ונמזג את כל השינויים עד הקומיט הראשון. כותבים הודעת קומיט יפה שמתארת כלל השינוי ולוחצים על REBASE בחזרה ל-MASTER. למעשה כיווצנו את השינוי לקומיט בודד ושמנו אותו מעל הHEAD של המאסטר העדכני. המוטיבציה לכך היא שנרצה שה-MASTER שלנו תמיד יראה לינארי, קומיטים של פיצ'רים מלאים, ללא כל MERGE COMMITS. בשיטת ה-REBASE הדבר הזה ודאי מבחינת פרטיקה ותאוריה.

בשיטת ה-MERGE - יש שתי אופציות עיקריות של MERGE-ים: REGULAR ו-SQUASH. בתרחיש שלנו, אנחנו נשתמש כמעט תמיד ב SQUASH. ב-REGULAR MERGE נוצר לנו MERGE COMMIT וזה יבטיח לנו שלא יהיה עץ MASTER לינארי. במקרה שלנו, סביר שלא נראה לשמור קומיטים בודדים מתהליך הפיתוח, אלא רק קומיט שמתאר כל הפיצ'ר, לכן REGULAR MERGE תהיה בחירה חריגה. לעומת זאת האופציה השנייה, SQUASH AND MERGE, ממזגת את כל הבראנצ' שלנו לקומיט בודד ומכניסה אותו למאסטר ללא MERGE COMMIT (במקרה כזה הקומיט שנוצר מפעולת ה-SQUASH AND MERGE יכיל הצבעה רק לאב הישיר שלו במאסטר)

מה אני ממליץ לכם כחלק מהכתיבה של הדברים האלה?
- אם על הבראנצ' פיתוח הזה עובד יותר מאדם אחד, תעבדו רק בשיטת ה-MERGE. במקרה כזה GIT PUSH –FORCE אחד לא במקום ואתם עלולים למחוק לקולגה שלכם את כל העבודה.
- בואו נתחיל מהאמת הפשוטה- אתם יכולים לעבוד ולעשות קומיטים עם הערות של WIP בלי שום משמעות ובסוף למזג עם SQUASH AND MERGE, זה יעבוד. אם אתה עובדים ככה - לקומיטים שלכם אין אפילו משמעות סמלית בעינכם, אלא רק כדרך לוודא שהקוד שלכם שמור במידה והמחשב שלכם יעלה בלהבות. במקרה כזה תעבדו עם השיטת ה-MERGE ותדאגו לעשות SQUASH AND MERGE במיזוג ל-MASTER עם הודעה טובה. חובה SQUASH AND MERGE כמו שהסברנו, כי נרצה שכל הפיצ'ר בבראנצ' MASTER יהיה בקומיט יחיד ובמיוחד אם הקומיטים שלכם לא מכילים שום מידע אינפורמטיבי.
- אם אתם עובדים בצורה יותר מבנית ודואגים לקומיטים מסודרים תשתמשו בשיטת ה-REBASE, ולרב היא תעבוד לכם בלי בעיות. אך אם בכל זאת מתגלה שיש לכם שינוי עם נטייה לקונפליקטים רבים בתהליך היישור (למשל שינוי ריפקטורינג), עדיף לחסוך את עוגמת הנפש של השיטת ה-REBASE ולעבור לשיטת ה-MERGE באמצע. קחו בחשבון אחרי המעבר לשיטת ה-MERGE תהיו מאד מגובלים בשליטה על העץ קומיטים שלכם. כמו מקודם, בסוף לדאוג לבצע SQUASH AND MERGE