פוסט
Git מאפס לגיבור: rebase וכלים שימושיים
חלק 5 במדריך ל-Git: rebase והכלל היחיד שבא איתו, rebase אינטראקטיבי לסידור commits, ואחר כך stash, cherry-pick, bisect ו-.gitignore.
בחלק 4 חיברנו את ענף הפיצה ל-main במיזוג. rebase היא הדרך השנייה לעדכן ענף.
rebase: חלופה מסודרת יותר
מיזוג שומר את ההיסטוריה האמיתית, כולל ההתפצלות. rebase מריצה מחדש את ה-commits של הענף על גבי ה-main העדכני, וההיסטוריה הופכת לקו ישר אחד:
git switch pizza
git rebase main
D′ ו-E′ הם commits חדשים עם מזהים חדשים, עותקים של המקוריים. מכאן הכלל היחיד ששווה לשנן:
לעולם לא עושים rebase ל-commits שכבר יש לאחרים. זה משכתב היסטוריה, וכל מי שמשך את ה-commits הישנים נשאר עם בלגן. על ענף פרטי אפשר לעשות rebase חופשי. ברגע שהוא משותף, ממזגים.
rebase אינטראקטיבי: לסדר את ה-commits
לפני ששיתפנו ענף, מסדרים את ההיסטוריה הפרטית שלו עם git rebase -i. נניח שהאחרון משלושה commits הוא רק תיקון שגיאת כתיב:
git rebase -i HEAD~3
Git פותח בעורך רשימה, מהישן לחדש. (בגרסאות ישנות ההודעה מופיעה בלי ה-#, ושתי הצורות עובדות.)
pick 3f2a1b9 # Add pasta recipe
pick 9c1d4e2 # Add salt to pasta
pick b7e3f10 # Fix typo in salt step
משנים את המילה בתחילת שורה כדי להגיד מה יקרה לאותו commit, ואז שומרים וסוגרים:
| מילה | מה היא עושה |
|---|---|
pick |
משאירה את ה-commit כמו שהוא |
reword |
משאירה אותו, אבל עוצרת כדי שנערוך את ההודעה |
squash |
מאחדת אותו ל-commit שמעליו ומשלבת את ההודעות |
fixup |
מאחדת אותו ל-commit שמעליו וזורקת את ההודעה שלו |
drop |
מוחקת את ה-commit |
edit |
עוצרת כדי שנוכל לשנות את תוכן ה-commit |
שינוי pick ל-fixup בשורה האחרונה מאחד את תיקון הכתיב לתוך “Add salt to pasta”, ונשארים שני commits נקיים. אפשר גם לסדר commits מחדש בהזזת שורות, ו-git rebase --abort מבטלת הכול.
כלים שימושיים
stash מניח בצד עבודה לא גמורה כדי לעבור לענף אחר עם תיקייה נקייה:
git stash push -m "half-written pasta tips"
git switch other-branch
# ... עושים משהו ...
git switch -
git stash pop # מחזירה אותה
cherry-pick מעתיקה commit בודד מענף אחר:
git cherry-pick 7c8d9e0
bisect מוצאת איזה commit הכניס באג, בחיפוש בינארי. נותנים ל-Git commit אחד שבור ואחד תקין, ואז עונים “good” או “bad” בזמן שהוא עובר על אלה שביניהם:
git bisect start
git bisect bad # ה-commit הנוכחי שבור
git bisect good v1.0 # זה עבד
# בודקים, ואז עונים: git bisect good / git bisect bad
git bisect reset # בסיום
.gitignore מפרט קבצים ש-Git לא אמור לעקוב אחריהם לעולם (תלויות, פלט build, סודות):
node_modules/
dist/
.env
כמה כללי תבנית מכסים כמעט הכול:
*.log # כל קובץ שמסתיים ב-.log
build/ # תיקייה, בכל מקום
/todo.md # רק בשורש הפרויקט
**/temp # "temp" בכל עומק
!keep.log # חריג: לעקוב אחרי זה למרות ש-*.log מוסתר
.gitignore משפיע רק על קבצים ש-Git עדיין לא עוקב אחריהם. אם קובץ נכנס ל-commit לפני שהסתרנו אותו, מריצים פעם אחת git rm --cached <קובץ> כדי להפסיק לעקוב אחריו (הקובץ נשאר בדיסק), ואז עושים commit. סיסמה או טוקן שהגיעו ל-commit דלפו גם אחרי המחיקה: קודם מבטלים ומחליפים, ורק אחר כך מנקים את ההיסטוריה.