יצירת Feature Branch

מתי צריך לעשות קומיט? ואיך כדאי לפתח כדי לצמצם קונפליקטים? והאם בכלל כדאי? בשיעור זה נדבר על תהליכי פיתוח מבוססי גיט ועל טכניקה בשם Feature Branch שעוזרת לצמצם קונפליקטים.

1. מתי עושים קומיט? מתי עושים Push?

השאלות "מתי כדאי לעשות קומיט?" ו"מתי כדאי לעשות Push?" יכולות להשפיע על כל תהליך העבודה שלנו בעבודה עם גיט. נהוג להגיד שאנחנו רוצים לעשות קומיט לעתים קרובות, כי כל קומיט מייצג נקודת שמירה. לא הייתם רוצים להגיע למצב שאתם צריכים לחזור אחורה אבל אין קומיט לחזור אליו.

פעולת Push היא כבר יותר עדינה, כי מרגע שדחפתי את הקומיטים אנשים אחרים צריכים למשוך אותם לפני שיוכלו לדחוף קומיטים שלהם, ולפעמים להתמודד עם קונפליקטים. בעצם זה שאני דוחף קומיטים לתיקייה המשותפת אני עלול להאט עבודה של אנשים אחרים או להכריח אותם לתקן דברים שהם כתבו כדי להתמודד עם הקונפליקט.

יש צוותים בהם התרבות היא לעשות Push לעתים קרובות. המחשבה היא שעדיף להתמודד עם הקונפליקטים כמה שיותר מוקדם, וממילא אם כולם עושים Push לעבודה שלהם כל כמה שעות או כל יום אז לא יהיו יותר מדי קונפליקטים.

ויש צוותים בהם התרבות היא לחכות עם ה Push עד שהקוד גמור, עובד ונבדק, כדי לצמצם את הסיכוי שאנשים אחרים בצוות יצטרכו להתמודד עם באגים שנגרמו כתוצאה מקוד לא גמור של אחד המפתחים.

גם בצוותים מהסוג השני, שמעדיפים לדחות את ה Push עד שהכל עובד, לפעמים אנחנו רוצים להעתיק את הקוד שלנו לתיקייה משותפת. זה יכול להיות בשביל להראות את הקוד למפתחים אחרים ולקבל חוות דעת או עזרה שלהם, או בגלל שהצוות גדול ויש מספר מפתחים שעובדים על כל פיצ'ר. בשיעור זה נראה איך להשתמש ב Branch-ים של גיט כדי לאפשר שיטת עבודה כזאת בטכניקה שנקראת Feature Branch.

2. קצת תיאוריה

ה Feature Branch הוא Branch שאנחנו פותחים לצורך עבודה על פיצ'ר מסוים. בניגוד לבראנץ של גירסה, ה Feature Branch נועד בשביל להיעלם, כלומר ברגע שהקוד יעבוד כמו שצריך נוכל להעביר את הקומיטים לגירסה הראשית ולמחוק את ה Feature Branch. כל המטרה של Feature Branch היא לאפשר לנו להעלות לתיקייה המשותפת בגיטהאב עבודה זמנית, כשאנחנו עובדים בצוות שהאנשים האחרים מעדיפים שלא נפריע להם עם הדברים הלא גמורים שלנו.

עבודה עם Feature Branch תיראה כך:

  1. אני מקבל דרישה ממנהל הפרויקט לממש פיצ'ר מסוים.

  2. אני פותח Feature Branch לצורך העבודה ומתחיל לכתוב את הקוד.

  3. כל כמה שעות או אפילו כמה פעמים בשעה אני עושה קומיט, כדי שיהיה לי לאן לחזור אם צריך.

  4. בסוף כל יום אני דוחף את ה Feature Branch שלי לתיקייה המשותפת. רוב האנשים שעובדים איתי על הפרויקט לא יסתכלו על הקוד, אבל מנהל הפרויקט ואולי אנשים אחרים שכן צריכים להסתנכרן עם העבודה שלי יוכלו למשוך את אותו Feature Branch כדי לראות את הקוד.

  5. בסוף העבודה על הפיצ'ר, כשכולם משוכנעים שהכל עובד כמו שצריך, אני מעתיק את הקומיטים מה Branch לגירסה הראשית של היישום ומוחק את ה Feature Branch.

עכשיו בואו נראה איך זה עובד דרך דוגמה אמיתית.

3. דוגמה: פיתוח בעזרת Feature Branch

נחזור לפרויקט ה AI שהתחלנו בשיעור הקודם ובואו נניח שאנחנו רוצים לעבור לפתח באמצעות Feature Branch. אני יוצר ענף חדש בשם feature/smart-responses, וכן אפשר להשתמש בלוכסן כחלק משם הענף ולפעמים זה נחמד.

אני עובר ל REPL כדי לתקן את הקוד כך שהתשובות של הבוט יהיו חכמות יותר ומשנה את הקובץ repl.py לתוכן הבא:

import sys

def start():
    try:
        while True:
            line = input()
            print(line)
            print("Ain't I the smartest?")
    except EOFError:
        print("Leaving so soon? ok bye")

ואז קומיט.

אחרי זה אני נזכר שצריך לכתוב גם הערות, אז שוב משנה את הקובץ לתוכן הבא:

import sys

def start():
    """
    Start the REPL to talk to the smartest AI in the world
    :return: 
    """
    try:
        while True:
            line = input()
            print(line)
            print("Ain't I the smartest?")
    except EOFError:
        print("Leaving so soon? ok bye")

ואז קומיט נוסף.

בזמן העבודה שלי מפתחים אחרים המשיכו לעבוד על ענף main הראשי. בשביל הדוגמה נעשה כאילו אנחנו המתכנתים האחרים - נחזור לענף main ונבצע שם מספר שינויים. קודם כל מישהו הכניס הודעת TODO לקוד בקובץ repl.py:

import sys

def start():
    try:
        while True:
            line = input()
            # TODO make responses smarter
            print(line)
    except EOFError:
        print("Leaving so soon? ok bye")

ובקומיט נוסף הוסיפו קובץ בשם readme.txt עם התוכן הבא:

this is the best AI bot in the world

שימו לב מה קורה כשאני מעלה את הפרויקט לתיקייה המשותפת: כפתור Publish מופיע כשאני על ענף main, אני לוחץ עליו ונכנס לדף הפרויקט בגיטהאב. שם אני יכול לראות את רשימת הענפים אבל הענף החדש שיצרתי לא מופיע. אני חוזר ל Github Desktop, עובר לענף feature/smart-responses ושם שוב מופיע לי כפתור Publish הפעם Publish Branch. בעצם כשאנחנו מעלים קוד לתיקייה המשותפת אנחנו מעלים את הקוד מהענף עליו אנחנו עכשיו מסתכלים.

4. שילוב הקוד מהענף

אחרי פירסום הענף הופיע באפליקציה כפתור חדש עם הטקסט Preview Pull Request. כפתור זה מראה את השינויים של ה Feature Branch ביחס לענף הראשי. אם אני מרוצה מהשינויים אני לוחץ על כפתור ההמשך ששולח אותי לממשק ה Web באתר github.com. כאן אני יכול להסביר מה המטרה של הענף שלי ולמה אני חושב שאפשר למזג אותו חזרה לענף הראשי. אני לוחץ שוב על הכפתור הירוק Create Pull Request ובקשת המיזוג נוצרה.

לגיט יש שני מנגנונים בהם הוא מעתיק קומיטים לענף הראשי, אחד נקרא merge והשני נקרא rebase. אנחנו נרחיב בקורס ההמשך על שני מנגנונים אלה וגם נבין מתי להשתמש בכל מנגנון, אבל באופן כללי ובטח בשלב בו אנחנו נמצאים אפשר לבחור את ברירת המחדל וללחוץ Merge Pull Request.

המיזוג הכניס את הקומיטים שלי לענף הראשי, בנוסף לקוד שכבר היה שם כולל לקוד שנכתב שם אחרי שאני כתבתי את הקומיטים שלי, כלומר אנחנו רואים שהערת ה todo שכתבתי עדיין נשארה בענף הראשי, ובנוסף אליה גם הקוד מה Feature Branch. גיט בעצם שילב את הקוד מה Feature Branch בתוך המערכת.gg נשארה רק משימה אחת - למחוק את ה Feature Branch מאחר והפיצ'ר גמור. גיט מאוד לא אוהב שאתם ממשיכים לשים קומיטים על Feature Branch שכבר מיזגתם ואז ממזגים את אותו Feature Branch פעם שנייה. זה יכול לגרום לתוצאות מפתיעות ולא נעימות.

מתוך הממשק של Github Desktop אני לוחץ על תיבת הענפים, כפתור ימני על שם ה Feature Branch ובוחר Delete. שימו לב לסמן בתיבה שהענף יימחק גם על התיקייה המרוחקת.

5. עכשיו אתם

אתם כבר יודעים מה עושים עכשיו. קחו את ה Workflow שראינו וחזרו עליו עם Feature Branch שאתם ממציאים:

  1. צרו את ה Feature Branch והכניסו אליו מספר קומיטים.

  2. הוסיפו מספר קומיטים לענף הראשי.

  3. מזגו חזרה את ה Feature Branch לענף הראשי דרך Pull Request, ולאחר מכן מחקו את ה Feature Branch.

בונוס: נסו ליצור קונפליקט בין ה Feature Branch לענף הראשי. איך גיט מתנהג במצב כזה? תקנו את הקונפליקט והמשיכו בדוגמה.