פתרון קונפליקטים

קונפליקט (conflict) קורה כאשר git לא מצליח למזג אוטומטית בין שני branches - בדרך כלל כי שניהם שינו את אותן שורות באותו קובץ. כל מי שעובד עם git ייתקל בזה - וזה לא מפחיד אחרי שמבינים את התהליך.

מתי קורה קונפליקט?

  • בעת git merge - שני branches שינו את אותו קוד
  • בעת git rebase - דומה, על בסיס שונה
  • בעת git pull - ה-main המקומי שלכם וה-main של השרת התקדמו אחד מהשני
  • בעת git cherry-pick - ה-commit שאתם מעתיקים נוגע באותו קוד

איך נראה קובץ עם קונפליקט?

git מסמן את הקונפליקט בתוך הקובץ עם סימנים מיוחדים:

function greet(name) {
<<<<<<< HEAD
  return `Hello, ${name}!`;
=======
  return `Hi there, ${name}!`;
>>>>>>> feature/friendly-greeting
}

הסימנים אומרים: - <<<<<<< HEAD - מתחיל הצד שלכם (ה-branch הנוכחי, בדרך כלל main) - ======= - מפריד בין שתי הגרסאות - >>>>>>> feature/friendly-greeting - מסיים את הצד הנכנס (ה-branch השני)

תהליך פתרון - שלב אחר שלב

1. זיהוי הקבצים בקונפליקט

git status

תראו משהו כמו:

both modified:   src/greet.js
both modified:   src/utils.js

2. עריכת הקבצים

פותחים כל קובץ בעורך. שלוש אפשרויות:

א. לבחור גרסה אחת

function greet(name) {
  return `Hi there, ${name}!`;
}

ב. לשלב את שתיהן

function greet(name) {
  return `Hi ${name}, hello!`;
}

ג. לכתוב משהו חדש לגמרי שמתחשב בשני הצדדים

חשוב: למחוק לחלוטין את הסימנים <<<<<<<, =======, >>>>>>>.

3. סימון כפתור

git add src/greet.js
git add src/utils.js

(או git add . אם פתרת את כולם)

4. סיום ה-merge

git commit

git יפתח עורך עם הודעה אוטומטית. אפשר להשאיר את ההודעה הזו ולשמור.

5. בדיקה שהכל תקין

git status
git log --oneline -5

דוגמה מלאה

# התחלנו merge
git merge feature/new-design

# קיבלנו:
# Auto-merging src/Header.jsx
# CONFLICT (content): Merge conflict in src/Header.jsx
# Automatic merge failed; fix conflicts and then commit the result.

# בודקים מה במצב קונפליקט
git status

# פותחים את src/Header.jsx, מתקנים, שומרים
# (עורכים ידנית)

# מסמנים כפתור
git add src/Header.jsx

# ממשיכים את ה-merge
git commit

ביטול merge בעיצומו

אם החלטתם שאתם לא רוצים להמשיך עם ה-merge:

git merge --abort

הפקודה תחזיר את הכל למצב שלפני שהתחלת את ה-merge.

עבור rebase:

git rebase --abort

כלים שמקלים על פתרון קונפליקטים

VS Code

VS Code מציג את הקונפליקטים בצורה ויזואלית עם כפתורים: "Accept Current Change", "Accept Incoming Change", "Accept Both Changes", "Compare Changes". שימוש מאוד פשוט.

Mergetool

git mergetool

פותח את ה-mergetool שהגדרת (vimdiff, meld, kdiff3 וכו').

טיפים למניעת קונפליקטים

  • סנכרון תכוף: git pull או git fetch && git merge כל יום
  • branches קצרים: ככל שה-feature חי יותר זמן, יותר קונפליקטים יצטברו
  • תיאום עם הצוות: אם יודעים שמישהו עובד על אותו קובץ - מדברים
  • commits אטומיים: שינויים קטנים וממוקדים קל יותר למזג

מה לא לעשות בקונפליקט

  • ❌ אל תמחקו את כל הקובץ ותכתבו מחדש - אתם עלולים לאבד שינויים חשובים
  • ❌ אל תשאירו את הסימנים <<<<<<< בקוד - הקוד לא יקומפל
  • ❌ אל תעשו git checkout -- על קובץ שיש בו קונפליקט - תאבדו עבודה
  • ❌ אל תיבהלו - קונפליקטים זה חלק רגיל מהעבודה

בדקו את עצמכם

נסו לענות לבד לפני שאתם פותחים את התשובה.

  1. מתי נוצר קונפליקט?

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

    תשובה ד. Git לא יכול להחליט לבד איזו גרסה נכונה.

  2. מה עושים אחרי שפותרים קונפליקט ידנית בקובץ?

    1. git init
    2. git reset
    3. מוחקים את הסימונים, git add לקובץ, ואז git commit
    4. git push מיד
    הצגת התשובה

    תשובה ג. add מסמן שהקונפליקט נפתר.