ניהול גרסאות

למה אתם *חייבים* ניהול גרסאות – גם כשמתכנתים בבית

כל מי שהוא חלק מצוות פיתוח בחברה יעיד שהוא משתמש בכלי ניהול גרסאות (source control) כלשהו כגון Subversion, Git, Team Foundation וכד'. ואכן כשמספר אנשים עובדים על אותו קוד היתרונות של כלי כזה הם עצומים, והוא פותר בעיות בסיסיות מאוד כמו: איפה שמור הקוד? מה קורה כששניים עובדים במקביל על אותו קובץ? איך מתעדים מה כל אחד עשה? וכד'.

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

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

כלי ניהול גרסאות במשפט אחד

את התפקיד הבסיסי של כל כלי ניהול גרסאות באשר הוא ניתן לנסח כך:

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

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

איך זה נראה בפועל? לרוב מדובר בתיקייה בודדת שנוצרת בתוך התיקייה הראשית של הקוד שלכם, ומכילה את היסטוריית הקוד כולה:

source-control

בדוגמה שלנו, השתמשתי בכלי ניהול הגרסאות Git, המייצר תיקייה בשם .git (שימו לב לנקודה בתחילת השם).

ניהול גרסאות למפתח יחיד

מעבר לייתרונות של סנכרון בין חברי הצוות ואחסון הקוד במקום מרוכז (רפוזיטורי, repository), כלי ניהול גרסאות, ביחד עם כלי ה-GUI הנלווים אליהם, מציעים שירותים רבים המייעלים מאוד את העבודה של מתכנת יחיד. להלן היתרונות המרכזיים.

די לפחד משינויים

אם אי פעם כתבתם קוד ללא שימוש ב-source control, בוודאי קרה לכם שהייתם צריכים לבצע שינוי בקוד, אבל לא רציתם לאבד את הקוד הנוכחי, אולי כי אתם עדיין צריכים אותו, ואולי כדי שתוכלו לחזור אליו בעתיד. עבור שינוי של שורה או שתיים, העתקה הצידה של הקוד או הסתמכות על פונקציית ה-undo של עורך הטקסט יכולות להספיק, אבל מה אם נרצה לשנות קוד רב? כאן אנחנו נתקלים בטכניקות מפוקפקות כמו שכפול הקובץ כולו לצורך גיבוי ופתרונות יצירתיים אחרים.

בעזרת שימוש פשוט מאוד בכלי ניהול גרסאות, אנחנו יכולים לבצע שינויים כאוות נפשנו. כל מה שעלינו לעשות הוא commit לקוד הנוכחי, כלומר שמירת הגרסה הנוכחית של הקוד בכלי ניהול הגרסאות, וכעת ניתן לערוך את הקוד ללא חשש. אם נרצה לחזור לקוד הישן, תמיד נוכל לעשות revert (חזרה לגרסה השמורה האחרונה), ואפילו לשמור את השינויים עצמם בצד לשימוש עתידי.

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

למה עשיתי את זה?!

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

אך אחרי כתיבת הרבה קוד (לפעמים מעט) מגיע הרגע הזה בו אני לא זוכר למה כתבתי שורה או שורות מסויימות, ומגלה בדיעבד שהייתי צריך להוסיף הערה. המקום שמספק את התשובות ב-90% מהמקרים הוא היסטוריית הקוד.

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

כעת כאשר נרצה לדעת מדוע ומתי קטע קוד כלשהו נכתב, נוכל לעיין בהיסטוריית השינויים (revision history) של הקובץ ולקרוא את ההודעות שהשארנו לעצמנו. ניתן אפילו לקבל דו"ח מפורט על השינויים שבוצעו בכל שורה ושורה בקובץ ע"י פקודת annotate file, או בשמה הכן יותר – blame :)

באופן כללי יותר – ניתן לחזור לכל נקודה בזמן, לראות איך היה נראה הקוד אז, ולנסות להבין את ההיגיון שעמד מאחורי כתיבת שורות כאלו או אחרות.

חשוב לציין שכדי שהיסטוריית השינויים תהיה שימושית, רצוי לבצע commit לאחר סיום של כל פיצ'ר או שינוי, ולפעמים אף ביניהם.

רגע, מה עשיתי עכשיו?

סוג שונה של מעקב אחר שינויים הוא מעקב אחרי השינויים שעשינו מאז ה-commit האחרון. זה אולי נשמע מוזר, אבל כמה פעמים שכחתם בקוד שלכם פקודת print שלא צריכה להיות שם או console.log מיותר?

הכלים הגרפיים לניהול גרסאות כמו Tortoise Git, TortoiseSVN וכד' מאפשרות לנו לראות בצורה נוחה את כל השינויים שביצענו, ולעבור על הקוד לפני שאנחנו מבצעים commit. ואכן לפני כל commit, אני אוהב לעבור במהירות על השינויים שביצעתי, לוודא שאני לא מכניס שטויות לקוד ושהקוד עומד בסטנדרטים שהצבתי לעצמי. ברוב המקרים אני מוצא משהו לתקן, והורג באגים עוד לפני שהם נולדים.

בשילוב עם תוכנת השוואת קבצים (Diff) חזקה כמו Beyond Compare, הצובעת את הקוד ומאפשרת עריכתו, המעבר על השינויים הופך יעיל במיוחד.

Source control diff
אופס, זה לא אמור להיות פה…

עבודה על מספר גרסאות במקביל

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

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

כלי ניהול גרסאות מספקים שירות המיועד למקרים מסוג זה. שירות זה נקרא ענפים (branches). כל ענף מכיל גרסה שונה מעט של הקוד שלנו, עם commits משלו והיסטוריה משלו. ניתן בקלות להחליף את הענף הנוכחי עליו אנו עובדים.

ה"קפיצה" הזאת בין ענפים תשנה בבת-אחת את כל קבצי הקוד בתיקייה לגרסה הרצוייה, ותאפשר לנו לערוך אותה, לבצע commits ולשחרר גרסאות בדיוק כאילו לא ביצענו בה שינויים. לאחר תיקון הענף הבעייתי (לרוב יהיה זה הענף הראשי, default branch, או הגזע, trunk) נוכל לקפוץ בחזרה לענף החדש ולהמשיך לעבוד עליו.

כדי לייצר ענף חדש לרוב נשתמש בפקודה branch <new branch> שלמעשה אומרת לכלי ניהול הגרסאות "כל השינויים שאבצע מעתה צריכים להיכנס לענף new branch".

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

Source Control Branches
עבודה עם ענפים. בדוגמה זאת יצרתי את הענף הכחול מתוך הענף הירוק ועבדתי על שני הענפים במקביל. לבסוף איחדתי את שני הענפים ע"י ביצוע merge.

גיבוי

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

במידה ואבד לנו הקוד מהמחשב האישי, תמיד נוכל לשחזר אותו, כולל כל ההיסטוריה, משירותים אלו.

תהליך העבודה שלי

לאחר שלמדנו למה כלי ניהול גרסאות הוא חשוב מאוד גם בעבודה לבד, להלן סיכום המציג את תהליך הפיתוח שלי כאשר אני עובד על פרוייקטים לבד (ללא שימוש בענפים):

Source Control Process

התחילו כבר עכשיו!

אם כל מה שתיארתי עד עכשיו נשמע מסובך – אל דאגה, ההבנה תגיע עם הזמן. בינתיים פשוט בצעו את השלבים הבאים כדי להתחיל. הדוגמה מתייחסת לכלי ניהול הגרסאות Mercurial על Windows, אך מתאימה גם ל-Git ודומיהם.

  1. הורידו והתקינו את הכלי TortoiseHg.
  2. פתחו את התיקייה בה נמצא הקוד שלכם, לחצו מקש ימני ואז TortioseHg -> Create Repository Here ובחלונית שנפתחה לחצו Create. בשלב זה תיווצר תיקיה בשם .hg וקובץ נוסף.
  3. לחצו מקש ימני על תיקיית הקוד שלכם (לא על התיקייה שנוצרה), ואז Hg Commit.
  4. סמנו את קבצי הקוד אותם תרצו להוסיף לניהול הגרסאות. בד"כ יהיו אלו כל קבצי הקוד בלבד, ולא קבצים ותיקיות הנוצרים אוטומטית כמו קבצי exe, pyc וכד'.
  5. הזינו הודעה קצרה כגון "First commit" ולחצו Commit.
  6. אם נשאלתם האם להוסיף את הקבצים שסומנו, לחצו Add.

זהו! הקוד שלכם עכשיו מנוהל גרסאות! עכשיו אתם מוכנים לבצע את השינוי הראשון שלכם.

  1. ערכו את אחד מקבצי הקוד.
  2. לחצו מקש ימני על הקובץ או התיקיה, ולחצו Hg Commit.
  3. ברשימת הקבצים בצד שמאל תוכלו לראות את כל הקבצים שהשתנו, ובצד ימין את השינויים בכל אחד מהם.
  4. לצפייה בשינויים בתוכנה מתקדמת יותר, לחצו לחיצה כפולה על הקובץ הרצוי.
  5. כעת ניתן לכתוב הודעה ולבצע commit.
  6. לחצו מקש ימני על הקובץ ואז TortoiseHg -> Revision History לצפייה בהיסטוריית השינויים של הקובץ.

10 תגובות בנושא “למה אתם *חייבים* ניהול גרסאות – גם כשמתכנתים בבית”

  1. פוסט מעולה! תודה רבה!

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

    אולי זה בכלל דורש פוסט בפני עצמו?

    1. תודה!

      אכן יש הרבה כלי ניהול גרסאות בשוק, כאשר הנפוץ ביותר היה עד לא מזמן SVN ועכשיו הוא מוחלף לאט לאט ב-Git. ההבדל ביניהם הוא די משמעותי, ואני מציע שתקרא עליו. כלי דומה מאוד ל-Git הוא Mercurial, שנמצא בשימוש בין היתר ע"י Facebook, שאפילו בנו עבורו הרחבות. קיימים כלים נוספים כמו Team Foundation של מיקרוסופט (שעובד מצויין עם Visual Studio) וגם Clear Case ועוד.
      למתחילים הייתי ממליץ על Git או Mercurial, מכיוון שהן לא דורשות שרת וניתן להשתמש בהן מקומית כמו שהראיתי בדוגמה.

  2. פוסט נהדר,
    לאחרונה התחלתי להשתמש ב Visual Studio Code וגיליתי שיש לו גם אינטרגציה ממש נחמדה עם Git.
    כמו כן, אני ממליץ לנסות גם את Github Desktop למי שמעדיף GUI על פני CLI.
    https://desktop.github.com/

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

  4. וואו באמת פוסט מעולה!
    אינפורמטיבי ומדויק!

    אני עובד עם תוכנות שכתובות ב VBA(אקסל), והגיע השלב שניהול גרסאות ניהיה חיוני ביותר, האם התוכנות שהזכרת בפוסט מתאימות גם לVBA?
    יש תוכנה שעדיפה בסביבת עבודה הזאת?

    תודה מראש!

    1. תודה אלכסיי :)
      לא מכיר משהו ספציפי עבור VBA, אבל תמיד אפשר לשמור את הקוד בקובץ רגיל ואותו לנהל באמצעות git.

  5. זה פעם ראשונה שאני משתמש בתוכנה
    אני מקבל שגיאה אחרי השלב שאני מוסיף קבצים (שלב 5 שציינת )
    identify yourself to mercurial ואז זה זורק אותי החוצה ,
    ראיתי בגוגל שצריך להוסיף קובץ מסוים באיזה מקום שהשד יודע ,
    אשמח לעזרה צח .

כתיבת תגובה

האימייל לא יוצג באתר. (*) שדות חובה מסומנים