למה דווקא Git?

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

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

  1. שהמערכת תהיה מבוזרת.

  2. שהמערכת תהיה אמינה.

  3. שהמערכת תעבוד מהר.

הטענה שלו היתה שב 2005 הוא לא אף מערכת שעמדה ב-3 התנאים, ולכן הוא החליט לכתוב מערכת ניהול גירסאות בעצמו. או כמו שלינוס אמר אז בהתיחס למערכות הקיימות:

I can build something better in two weeks -- Linus Torvalds

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

1. גיט היא מערכת מבוזרת

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

  1. המאגר המרכזי פגיע - תקלה טכנית או פריצה יכולות לעשות נזק עצום, כיוון שכל ההיסטוריה וכל המידע של כולם שמור שם.

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

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

מערכת מבוזרת מצליחה להימנע מכל הבעיות האלה:

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

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

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

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

2. גיט היא מערכת אמינה

גיט מבטיחה לנו שמה שנכנס למאגר יוצא ממנו בדיוק באותה צורה, והיא עושה את זה באמצעות חישוב SHA1 על כל קומיט. אותו ערך שאתם רואים כשאתם מסתכלים ב Git Log בתור מזהה הקומיט:

$ git log -n 1 --oneline
e150874 (HEAD -> master) initial commit

אני מתכוון למספר הראשון שמופיע בשורה במקרה שלנו זה e150874. מזהה זה הוא ההתחלה של חישוב SHA1 על הקומיט. את הערך המלא אפשר לראות אם נתבונן בלוג בלי המתג oneline. במקרה שלי הוא נראה כך:

e150874e00e3dc5d26f0f4149963105abc788482

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

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

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

3. גיט היא מערכת מהירה

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

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

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

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

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