• בלוג
  • איך למזג קבצי JSON (או כל קובץ מיוחד אחר) עם git

איך למזג קבצי JSON (או כל קובץ מיוחד אחר) עם git

27/04/2021

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

דוגמה קלה היא קבצי JSON, ובמיוחד הקובץ package.json למתכנתי Front End או מתכנתי Node.JS. כשאנחנו מוסיפים מודול בענף אחד בגיט, ובענף אחר מוסיפים מודול אחר, כמעט תמיד נקבל קונפליקט. הנה דוגמה קטנה של package.json אחרי ניסיון merge, כשענף אחד התקין מודול בשם cowsay וענף אחר התקין מודול בשם mocha:

{
  "name": "driverdemo",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
<<<<<<< HEAD
  "dependencies": {
    "cowsay": "^1.4.0"
=======
  "devDependencies": {
    "mocha": "^8.3.2"
>>>>>>> feature2
  }
}

אם גיט היה קצת יותר חכם הוא היה מבין שאין קשר בין המפתח dependencies למפתח devDependencies, ושבשביל לשלב את הקבצים הוא פשוט צריך לשמור את שני המפתחות באוביקט הראשי. מסתבר שאנחנו יכולים ממש בקלות להפוך את גיט לקצת יותר חכם באמצעות מנגנון שנקרא Merge Driver.

דרייבר מיזוג, או merge driver, הוא פשוט תוכנית ש git יפעיל כשהוא צריך למזג שני קבצים. התוכנית תקבל בתור פרמטרים את שני הקבצים וגם את הקובץ בגירסת ה merge-base שלהם, כלומר הקובץ "המקורי" ממנו שניהם יצאו.

אנחנו יכולים לכתוב דרייברים ככל שנרצה ולבקש מגיט להפעיל אותם על קבצים מסוג מסוים באמצעות תוספת הגדרה בקובץ .git/config.

דרייבר מיזוג שכבר קיים ועובד טוב לקבצי JSON נקרא git-json-merge. אני ממליץ להסתכל גם על הקוד שלו כדי לראות איך נראה merge driver וכי בסך הכל הוא די פשוט. בשביל להתקין את הדרייבר נפעיל:

npm install --global git-json-merge

ועכשיו נמשיך להגדיר את git-json-merge בתור הדרייבר שימזג קבצי JSON בפרויקט שלנו. קודם כל יש ליצור בתיקיית הפרויקט קובץ בשם .gitattributes ובו התוכן הבא:

*.json merge=json

הקובץ מגדיר שכל קובץ עם סיומת json יהיה קובץ מסוג json. אתם יכולים לבחור כל מילה במקום json, וכל תבנית לתפיסת קבצים - כך שתוכלו להגדיר דרייבר מסוים שיפעל רק על קובץ אחד ספציפי, או על package-lock.json בלבד.

הקובץ השני בסיפור שלנו הוא .git/config שם נוסיף את הבלוק:

[merge "json"]
    name = custom merge driver for json files
    driver = git-json-merge %A %O %B

הפקודה git-json-merge היא התוכנית שהרגע התקנו, ושלושת האותיות אחריה מייצגות את שלושת הגירסאות של הקובץ: %A הקומיט מהענף הנוכחי, %O הקובץ המקורי מ merge-base ו %B הקובץ מהענף השני.

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

{
  "name": "driverdemo",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "mocha": "^8.3.2"
  },
  "dependencies": {
    "cowsay": "^1.4.0"
  }
}

ואם יש לכם קבצים נוספים בפורמטים יצירתיים שווה להסתכל בקוד של git-json-merge ולכתוב גירסה מותאמת למיזוג הקבצים שלכם.