שאלה של לקוחה שלחה אותי לחפש מה גיט עושה כשהוא כותב לנו שקובץ שינה את השם - והתשובה הפתיעה אפילו אותי. בואו נפתח מאגר בשביל לראות יחד.
אני בתיקיה חדשה כותב:
$ git init .
$ echo hello > file1.txt
$ git add .
$ git commit -m 'initial commit'
ועכשיו נשנה לקובץ את השם:
$ git mv file1.txt file2.txt
$ git status
On branch main
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
renamed: file1.txt -> file2.txt
$ git commit -m 'rename'
ואפשר לראות את שינוי השם גם בצפיה בלוג:
$ git log -p --oneline
25ccbd7 (HEAD -> main) rename
diff --git a/file1.txt b/file2.txt
similarity index 100%
rename from file1.txt
rename to file2.txt
0e6c0e3 initial commit
diff --git a/file1.txt b/file1.txt
new file mode 100644
index 0000000..ce01362
--- /dev/null
+++ b/file1.txt
@@ -0,0 +1 @@
+hello
עכשיו אנחנו יודעים שכל קומיט ב git הוא בסך הכל Snapshot של כל הקבצים בפרויקט. אנחנו יודעים שגיט לא שומר שינויים בין קומיטים וכשאנחנו מנסים למצוא שינויים הוא משווה בזמן אמת בין הקומיטים כדי לזהות את השינויים. במילים אחרות אנחנו יודעים שמבחינת גיט כל קומיט הוא פתית שלג ייחודי שמכיל את כל המידע של הפרויקט.
אז איך גיט יודע שקובץ שינה את השם בין קומיטים? איפה המידע הזה נשמר? ... מסתבר שבשום מקום. המפתח הוא ה similiarity index של הקבצים. כשאינדקס זה גבוה גיט מניח בסבירות גבוהה שמדובר באותו קובץ שפשוט שינה את השם.
זאת גם הסיבה שגיט יכול לזהות לבד כשקובץ שינה את שמו, ושלפעמים הוא טועה בזיהוי. כל זה הוא בסך הכל טקסט יפה שגיט משתמש בו כדי להסביר לנו דברים שהוא חושב שאולי קרו, אבל בעצם אין לו דרך מדויקת לדעת את זה.
והטריק להיום הוא המתג --no-renames
שאפשר לצרף להרבה פקודות גיט כדי לכבות את מנגנון זיהוי שינויי השם. כך אותו הלוג יראה בלי המנגנון:
$ git log -p --oneline --no-renames
25ccbd7 (HEAD -> main) rename
diff --git a/file1.txt b/file1.txt
deleted file mode 100644
index ce01362..0000000
--- a/file1.txt
+++ /dev/null
@@ -1 +0,0 @@
-hello
diff --git a/file2.txt b/file2.txt
new file mode 100644
index 0000000..ce01362
--- /dev/null
+++ b/file2.txt
@@ -0,0 +1 @@
+hello
0e6c0e3 initial commit
diff --git a/file1.txt b/file1.txt
new file mode 100644
index 0000000..ce01362
--- /dev/null
+++ b/file1.txt
@@ -0,0 +1 @@
+hello
הפעם במקום שינוי שם יש לנו מחיקה ויצירה של קובץ חדש. עבור אותו לוג.
גם diff יכול לקבל אותו טיפול והנה שתי האפשרויות:
$ git diff --name-status HEAD~
R100 file1.txt file2.txt
$ git diff --name-status --no-renames HEAD~
D file1.txt
A file2.txt
הבחירה להשתמש במנגנון זיהוי שינוי השמות של גיט היא שלכם, והיא לא קשורה לתוכן הקבצים עצמם שנשמרים במאגר. לפעמים מנגנון זה נוח ועוזר לראות מה קרה בלוג בצורה יותר מדויקת, אבל כשהוא לא עוזר לכם אל תתביישו לכבות אותו.