פיצול פרויקט עם Git Filter Branch
פוסט זה כולל טיפ קצר לעבודה יעילה יותר עם Git.
בשביל להבין את גיט לעומק אני ממליץ על קורס גיט שלנו כאן באתר.
בקורס תלמדו איך גיט עובד מתחת למכסה המנוע ואיך להשתמש בו בצורה יעילה מהבסיס ועד לנושאים המתקדמים.
מה שמבדיל בין מתכנתים שיודעים גיט לכאלה שקראו איזה מדריך מקוצר הוא היכולת להתאושש מטעויות. וככל שתעבדו יותר בגיט כך תלמדו שלפעמים טעויות שנראות פשוטות ממש מחייבות צעדים דרסטיים כדי להתאושש מהן. כך המקרה של פיצול פרויקט.
1. איך הגענו לכאן
אז נניח שאתם בונים פרויקט שמורכב מכמה חלקים ובתחילת העבודה אתם די בטוחים שיהיה נוח לשמור את הכל באותו מאגר גיט. כך אולי נראה עץ הפרויקט:
$ tree
.
├── app
│ ├── main.py
│ └── readme.md
└── common
├── __pycache__
│ └── utils.cpython-37.pyc
├── readme.md
└── utils.py
וכך נראה ה git log:
$ git log --oneline
92f1dab (HEAD -> master) add say_hi function
1d6afe9 add thrice to utils
9e14d07 add readme to common
e3bb78a add readme to main app
2b02b69 initial commit
לאורך זמן אתם אולי מגלים שבעצם לא כל כך מסתדר לכם ששני הפרויקטים נשמרים באותו מאגר. אולי מתכנתים מצוותים אחרים עובדים עליהם ונוצרים קונפליקטים שלא צריכים לקרות. בקיצור אתם מחליטים לפצל את הפרויקט. אבל איך עושים את זה?
2. פיצול פרויקט עם git filter-branch
הפקודה git filter-branch די טובה בעריכה של פרויקט גיט והיא תעזור לנו להיפטר מהחלקים "המיותרים". כדי לקבל פרויקט שמורכב רק מ app נוכל להעתיק את הפרויקט ואז למחוק מהעותק החדש את כל הדברים שקשורים לתיקיית common. תהליך דומה ייתן לנו פרויקט חדש רק עבור תיקיית common. בכל אחד מהפרויקטים נראה רק את הקומיטים שקשורים לקבצים שלו (כולל עבור קומיטים שבוצעו לפני הפיצול).
הפקודה הבאה תיצור עותק של הפרויקט עבור הפרויקט החדש app ותנקה את ההיסטוריה כך שנראה רק את הקומיטים הרלוונטים:
$ cp -R 02-change-root-demo 02-change-root-demo-app
$ cd 02-change-root-demo-app
$ $ git filter-branch --prune-empty --subdirectory-filter app
נבדוק בלוג לראות שהשינוי שלנו הצליח:
$ git log --oneline
204f907 (HEAD -> master) add say_hi function
1313e6c add readme to main app
daa9f93 initial commit
ואחרי שווידאתם שאין טעויות אפשר למחוק את הקומיטים הישנים באמצעות:
$ git for-each-ref --format='delete %(refname)' refs/original | git update-ref --stdin
$ git reflog expire --expire=now --all
$ git gc --prune=now
בצעו את אותו תהליך על common וקיבלתם שני פרויקטים שונים, כל אחד עם כל ההיסטוריה שרלוונטית עבורו לפי התיקיה הראשית של הפרויקט.
רוצים לשמוע עוד על filter branch ובכלל על אוטומציה בגיט? בואו לוובינר בשבוע הבא שידבר בדיוק על הנושאים האלה. הרשמה בחינם בקישור: