מאפייני קבצים
.gitattributes הוא הקובץ בעל הערך הגבוה ביותר ב־git שכמעט אף אחד לא כותב. זו
הדרך שבה מאגר מלמד את git על התוכן של עצמו: אילו קבצים בינאריים, אילו צריכים
להשתרשר במקום להתנגש, אילו לעולם לא יוצאים בארכיון, ואילו סופי שורה כולם מקבלים.
החלק החשוב: הוא נכנס לקומיט. כלל שתוסיפו מתקן את הבעיה לכל מי שמשכפל, בכל מערכת הפעלה, לנצח — בניגוד להגדרה בתצורה שלכם, שמתקנת את זה עבורכם ומשאירה את העמיתים שלכם לגלות את זה בדרך הקשה.
⌘K ← מאפייני קבצים.

מה הכללים עושים
| מאפיין | מתקן |
|---|---|
text=auto eol=lf |
סופי שורה שמתהפכים לפי מי עשה צ׳קאאוט לקובץ |
binary |
git שמנסה להשוות או למזג תלת־כיוונית PSD, DOCX או נכס מהודר |
merge=union |
יומן שינויים שכולם מוסיפים לו, וכולם מתנגשים עליו |
-merge |
קבצים שבהם מיזוג תלת־כיווני מייצר שטויות — קובצי נעילה, קוד מחולל |
export-ignore |
תצורת CI ופיקסצ׳רים שנשלחים בתוך tarball של ריליס |
diff=<driver> |
דיפים בלתי קריאים לפורמטים שכן קריאים, בהינתן ממיר |
filter=lfs |
קבצים גדולים שנשמרים דרך LFS |
linguist-vendored |
קוד מוטמע שנספר כשלכם בסטטיסטיקת השפות |
binary הוא קיצור ל־-diff -merge -text, שהוא שלוש תשובות ל״תפסיק לנחש לגבי
הקובץ הזה״ במילה אחת.
עריכה
הערכות המוכנות ממלאות תבנית ואת המאפיינים שלה; ערכו את התבנית לפני ההוספה —
CHANGELOG.md הוא הצעה, לא כלל על הפרויקט שלכם.
העריכות כירורגיות. הוספת כלל לתבנית שכבר יש לה אחד כותבת מחדש את השורה הזו במקומה, במקום לצרף כלל שני שמנצח בזכות היותו מאוחר יותר. ההערות בקובץ שורדות בלי שנוגעים בהן, כי ה״למה״ שליד כלל שווה בדרך כלל יותר מהכלל.
כל שמירה היא פעולת Gitcito רגילה: היא מציגה הודעה קופצת, וביטול משחזר את הקובץ בדיוק כפי שהיה.
למאגר יכולים להיות כמה קובצי מאפיינים. אחד בשורש, אחד בכל תת־תיקייה,
ו־.git/info/attributes פרטי שלעולם אינו נכנס לקומיט וחל רק במחשב שלכם — המקום
הנכון לכלל שנוגע לכם, לא לפרויקט. Gitcito מונה את כולם ואומר מי הוא מי.
מה חל על נתיב?
הכללים מגיעים מכמה קבצים, הספציפי יותר מנצח, וקריאה שלהם כדי לחשב את התשובה היא
ניחוש. מה חל על נתיב? מריץ git check-attr ומראה למה git עצמו מגיע — התשובה
היחידה שנחשבת.
דרייברי דיף: להפוך מסמך Word לקריא
.docx הוא zip. .pdf הוא גרף אובייקטים דחוס. git משווה אותם כמו שהם — רעש —
ולכן ההיסטוריה של מסמך בלתי קריאה גם כשהמסמך עצמו אינו כזה.
דרייבר דיף מתקן את זה עם textconv: פקודה שהופכת את הקובץ לטקסט לצורכי
השוואה בלבד. הקובץ בעץ העבודה שלכם אינו נגוע; git פשוט משווה את הטקסט שהומר.
שני חצאים, ושניהם נחוצים:
diff.<name>.textconvבתצורת git — פקודת הממיר.*.docx diff=<name>ב־.gitattributes— על אילו קבצים זה חל.
הכפתורים כאן עושים את שניהם בבת אחת. עבור Word, Excel, JSON ו־.strings, Gitcito מגיע
עם הממיר בעצמו — אותו ניתוח מסמכים שהתצוגות המקדימות שלו משתמשות בו, חשוף
כפקודה קטנה בשם gitcito-textconv בתוך האפליקציה — כך שארבעת אלה עובדים בלי
להתקין דבר. השאר עדיין זקוקים לכלי אמיתי ב־PATH שלכם: Gitcito בודק ומאפיר את
מה שחסר, במקום לכתוב דרייבר שנכשל בדיף הראשון.
| דרייבר | דורש | נותן לכם |
|---|---|---|
word |
כלום — מגיע עם Gitcito | דיפים של פרוזה ב־.docx |
excel |
כלום — מגיע עם Gitcito | דיפים של שורות (CSV לכל גיליון) ב־.xlsx/.xls |
json |
כלום — מגיע עם Gitcito | דיפים יציבים של JSON, ממוינים לפי מפתח |
strings |
כלום — מגיע עם Gitcito | הפרשים לפי שורות של .strings בקידוד UTF-16, ש-git קורא לו בינארי |
pdf |
pdftotext (poppler) |
דיפים טקסטואליים של .pdf |
exif |
exiftool |
מה השתנה בתמונה, כשהפיקסלים אטומים |
זה שבאמת נושך פרויקטי iOS
Localizable.strings הוא UTF-16 לאורך רוב ההיסטוריה של Xcode, ו-UTF-16 מלא
בבתי NUL — ולכן git קורא לו בינארי ולא מציג כלום:
diff --git a/Localizable.strings b/Localizable.strings
Binary files a/Localizable.strings and b/Localizable.strings differ
וזה בדיוק הקובץ שבו הכי חשוב לראות איזו מחרוזת מישהו הזיז. מנהל ההתקן strings
מפענח אותו לצורך ההשוואה בלבד — קורא את סימן סדר הבתים במקום להניח אותו, כך
ש-.strings מודרני ב-UTF-8 עובר כמות שהוא במקום להפוך לג'יבריש.
String Catalogs (.xcstrings, מ-Xcode 15 ואילך) הם JSON, ומנהל ההתקן json
מכסה אותם: הוא ממיין מפתחות, כך שתרגום שנוסף בראש הקובץ מפסיק לשכתב את כולו
בהפרש.
מגבלות הממיר המובנה, בפשטות: .doc (פורמט Word הבינארי הישן) אינו מובן, רק
.docx; PDF אינו מכוסה — Gitcito מציג תצוגה מקדימה של PDF עם המציג של
הדפדפן, ואין לו מחלץ טקסט לעשות בו שימוש חוזר; וכל דיף של מסמך משלם עלות
התנעה קצרה של הממיר. הגדרת git config diff.<name>.cachetextconv true גורמת
ל־git לשמור את הפלט במטמון לכל blob.
חצי הממיר חי בתצורה שלכם, לא במאגר — git לא יריץ פקודות ששכפול מוסר לו,
וזו תכונת אבטחה ששווה לשמור. הדרייברים המובנים גם מצביעים על נתיב ההתקנה של
Gitcito אצלכם, ולכן חבר לצוות שמשכפל מקבל את הכלל diff=word, ועד שיחבר
ממיר משלו (Gitcito או אחר) — את הדיף הישן והבלתי קריא. אמרו זאת ב־README שלכם.
מסנני clean/smudge — עם הרצה יבשה קודם
מסנן כותב מחדש תוכן בדרכו אל המאגר וממנו: clean רץ בהעלאה לאינדקס (עץ
העבודה ← מאגר), smudge בצ׳קאאוט (מאגר ← עץ העבודה). כך עובד git-lfs, וכך
צוותים מסלקים אישורי גישה או רעש מחולל ממה שנכנס לקומיט.
זה גם הדבר המסוכן ביותר ש־.gitattributes יכול להצביע עליו: מסנן רץ בכל
צ׳קאאוט של כל קובץ תואם, ומסנן שגוי משחית בשקט את עץ העבודה שלכם. לכן Gitcito
מסרב להיות כאן סתם תיבת טקסט. הגדרת מסנן עוברת דרך הרצה יבשה מול קבצים
תואמים אמיתיים במאגר שלכם:
- פקודת ה־
cleanרצה על עותק של כל קובץ תואם (עד חמישה) — שום דבר במאגר או בתצורתו אינו נגוע. - אם ניתנת פקודת
smudge, היא רצה על הפלט המנוקה והתוצאה מושווית בית אחר בית למקור — בדיקת ההלוך ושוב. מסנן שאינו עובר את ההלוך ושוב פירושו שצ׳קאאוט לא ישחזר את מה שהיה לכם. - רק אחרי הרצה יבשה על בדיוק הערכים שאתם שומרים, כפתור השמירה נדרך. הרצה יבשה שנכשלה — שגיאת פקודה, שום התאמה, או הלוך ושוב שונה — עדיין אפשר לשמור, אבל רק דרך אזהרה מפורשת שאומרת מה עלול ללכת לאיבוד.
שמירה כותבת filter.<name>.clean/smudge לתצורת git המקומית שלכם ואת הכלל
filter=<name> לקובץ המאפיינים, ומשאירה רשומת ביטול שמשחזרת את מה שהתצורה
החזיקה קודם. המתג required מגדיר filter.<name>.required, שגורם ל־git
להיכשל בפעולה במקום להעביר קבצים בשקט כמו שהם כשהמסנן נשבר.
המגבלות, בפשטות: ההרצה היבשה דוגמת עד חמישה קבצים תואמים של עד 5 MB כל אחד, עם
פסק זמן של 10 שניות לכל פקודה — מסנן שמתנהג יפה על המדגם עדיין יכול לקלקל קובץ
שהמדגם פספס. הפקודות חיות בתצורה שלכם, ולכן חבר לצוות שמשכפל מקבל את הכלל
filter=<name> אבל לא את הפקודות; בלעדיהן (ובלי required) הקבצים שלו עוברים
כמו שהם.
מגבלות ששווה להכיר
text=autoמשנה מה נכנס לקומיט, ומנרמל סופי שורה בדרך פנימה. במאגר קיים, הוסיפו אותו ואז הריצוgit add --renormalize .בכוונה, בקומיט נפרד משלו.- מאפיינים אינם חלים רטרואקטיבית. סימון קובץ כ־
binaryהיום אינו משנה איך הדיפים שלו בעבר נשמרו; הוא משנה איך git מתייחס אליו מעכשיו. - כללים חלים רק היכן שהקובץ נראה. כלל ב־
design/.gitattributesלא אומר דבר עלsrc/. - Gitcito כותב קבצים שלמים, ולכן קובץ שעוצב ביד חוזר עם העיצוב שלו — אבל כלל
ש־Gitcito כותב מחדש מעוצב מחדש לריווח הקנוני של git,
pattern attr attr.
ראו גם: LFS וצ׳קאאוט חלקי · חבילות וארכיונים · אפשרויות מיזוג · הוקים