במקום הקדמה
שלום! היום אנחנו הולכים לדבר על מערכת בקרת גרסאות, כלומר Git.
יסודות Git
Git היא מערכת בקרת גרסאות מבוזרת עבור הקוד שלנו. למה אנחנו צריכים את זה? צוותים מבוזרים זקוקים למערכת כלשהי לניהול העבודה שלהם. יש צורך לעקוב אחר שינויים המתרחשים לאורך זמן. כלומר, עלינו להיות מסוגלים לראות שלב אחר שלב אילו קבצים השתנו וכיצד. זה חשוב במיוחד כאשר אתה חוקר מה השתנה בהקשר של משימה בודדת, מה שמאפשר לבטל את השינויים.התקנת Git
בוא נתקין ג'אווה במחשב שלך.התקנה על Windows
כרגיל, עליך להוריד ולהפעיל קובץ exe. הכל פשוט כאן: לחץ על הקישור הראשון של גוגל , בצע את ההתקנה, וזהו. לשם כך, נשתמש בקונסולת bash שמספקת Windows. ב-Windows, אתה צריך להפעיל את Git Bash. כך זה נראה בתפריט התחל:

התקנה על לינוקס
בדרך כלל Git הוא חלק מהפצות לינוקס והוא כבר מותקן, מכיוון שמדובר בכלי שנכתב במקור לפיתוח ליבת לינוקס. אבל יש מצבים שלא. כדי לבדוק, אתה צריך לפתוח מסוף ולכתוב: git --version. אם אתה מקבל תשובה מובנת, אז שום דבר לא צריך להיות מותקן. פתח מסוף והתקן את Git באובונטו . אני עובד על אובונטו, אז אני יכול להגיד לך מה לכתוב עבורו: sudo apt-get install git.התקנה על macOS
גם כאן צריך קודם כל לבדוק אם Git כבר שם. אם אין לך את זה, אז הדרך הקלה ביותר להשיג את זה היא להוריד את הגרסה העדכנית ביותר כאן . אם Xcode מותקן, אז Git בהחלט יותקן אוטומטית.הגדרות Git
ל-Git יש הגדרות משתמש עבור המשתמש שיגיש עבודה. זה הגיוני והכרחי, מכיוון ש-Git לוקח את המידע הזה עבור שדה Author כאשר נוצרת commit. הגדר שם משתמש וסיסמה עבור כל הפרויקטים שלך על ידי הפעלת הפקודות הבאות:
git config --global user.name "Ivan Ivanov"
git config --global user.email ivan.ivanov@gmail.com
אם אתה צריך לשנות את המחבר עבור פרויקט ספציפי, אתה יכול להסיר את "--global". זה ייתן לנו את הדברים הבאים:
git config user.name "Ivan Ivanov"
git config user.email ivan.ivanov@gmail.com
קצת תיאוריה...
כדי לצלול לתוך הנושא, כדאי שנכיר לכם כמה מילים ופעולות חדשות...- מאגר git
- לְבַצֵעַ
- ענף
- לְמַזֵג
- קונפליקטים
- מְשׁוֹך
- לִדחוֹף
- כיצד להתעלם מקבצים מסוימים (.gitignore)
סטטוסים ב-Git
ל-Git יש כמה פסלים שצריך להבין ולזכור:- ללא מעקב
- שונה
- מְבוּיָם
- מְחוּיָב
איך אתה צריך להבין את זה?
אלו הם סטטוסים החלים על הקבצים המכילים את הקוד שלנו:- לקובץ שנוצר אך עדיין לא נוסף למאגר יש את הסטטוס "לא במעקב".
- כאשר אנו עורכים שינויים בקבצים שכבר נוספו למאגר Git, אז הסטטוס שלהם "משתנה".
- בין הקבצים ששינינו, אנו בוחרים את הקבצים שאנו צריכים, והמחלקות הללו משתנות לסטטוס "מבוים".
- commit נוצר מקבצים מוכנים במצב מבוים ונכנס למאגר Git. לאחר מכן, אין קבצים עם הסטטוס "מבוים". אבל ייתכן שעדיין יש קבצים שהסטטוס שלהם "משונה".

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

מה זה סניף?
ענף הוא מצביע על התחייבות כלשהי. מכיוון שמתחייב יודע איזו התחייבות קודמת לו, כאשר ענף מצביע על התחייבות, חלים עליו גם כל אותם התחייבויות קודמות. בהתאם, נוכל לומר שאתה יכול להחזיק כמה סניפים שאתה רוצה המצביעים על אותו commit. העבודה מתרחשת בסניפים, כך שכאשר נוצר commit חדש, הענף מעביר את המצביע שלו ל-commit האחרון.תחילת העבודה עם Git
אתה יכול לעבוד עם מאגר מקומי לבד וגם עם מאגר מרוחק. כדי לתרגל את הפקודות הנדרשות, אתה יכול להגביל את עצמך למאגר המקומי. זה מאחסן רק את כל המידע של הפרויקט באופן מקומי בתיקיית .git. אם אנחנו מדברים על המאגר המרוחק, אז כל המידע מאוחסן איפשהו בשרת המרוחק: רק עותק של הפרוייקט מאוחסן באופן מקומי. ניתן לדחוף שינויים שבוצעו בעותק המקומי שלך (git push) למאגר המרוחק. בדיון שלנו כאן ומטה, אנחנו מדברים על עבודה עם Git בקונסולה. כמובן, אתה יכול להשתמש באיזשהו פתרון מבוסס GUI (לדוגמה, IntelliJ IDEA), אבל תחילה עליך להבין אילו פקודות מבוצעות ומה משמעותן.עבודה עם Git במאגר מקומי
לאחר מכן, אני מציע לך לעקוב ולבצע את כל השלבים שעשיתי בזמן שקראת את המאמר. זה ישפר את ההבנה והשליטה שלך בחומר. ובכן, תאבון! :) כדי ליצור מאגר מקומי, עליך לכתוב:
git init

git status

- git add -A - הוסף את כל הקבצים לסטטוס "מבוים".
- git add . - הוסף את כל הקבצים מתיקיה זו ואת כל תיקיות המשנה. בעיקרון, זה זהה לקודם
- git add <שם קובץ> - מוסיף קובץ ספציפי. כאן אתה יכול להשתמש בביטויים רגולריים כדי להוסיף קבצים לפי דפוס כלשהו. לדוגמה, git add *.java: זה אומר שאתה רוצה להוסיף רק קבצים עם סיומת java.
git add *.txt
כדי לבדוק את המצב, אנו משתמשים בפקודה שכבר ידועה לנו:
git status

git commit -m "all txt files were added to the project"

git log

git status

git status

git diff

git add test_resource.txt
git commit -m "added hello word! to test_resource.txt"
כדי להסתכל על כל ההתחייבויות, כתוב:
git log

git add GitTest.java
git commit -m "added GitTest.java"
git status

עבודה עם .gitignore
ברור שאנחנו רוצים לשמור רק את קוד המקור לבד, ולא שום דבר אחר, במאגר. אז מה עוד יכול להיות? לכל הפחות, מחלקות ו/או קבצים הידור שנוצרו על ידי סביבות פיתוח. כדי להגיד ל-Git להתעלם מהם, עלינו ליצור קובץ מיוחד. עשה זאת: צור קובץ בשם .gitignore בשורש הפרוייקט. כל שורה בקובץ זה מייצגת דפוס שיש להתעלם ממנו. בדוגמה זו, קובץ ה-gitignore ייראה כך:
```
*.class
target/
*.iml
.idea/
```
בואו נסתכל:
- השורה הראשונה היא להתעלם מכל הקבצים עם סיומת .class
- השורה השנייה היא להתעלם מתיקיית ה"מטרה" ומכל מה שהיא מכילה
- השורה השלישית היא להתעלם מכל הקבצים עם סיומת .iml
- השורה הרביעית היא להתעלם מתיקיית .idea
git status


git add .gitignore
git commit -m "added .gitignore file"
ועכשיו רגע האמת: יש לנו מחלקה קומפילית GitTest.class שהיא "לא מעקב", אותה לא רצינו להוסיף למאגר Git. כעת אנו אמורים לראות את ההשפעות של קובץ .gitignore:
git status

עבודה עם סניפים וכאלה
מטבע הדברים, עבודה בסניף אחד בלבד אינה נוחה למפתחים בודדים, ואי אפשר כשיש יותר מאדם אחד בצוות. זו הסיבה שיש לנו סניפים. כפי שאמרתי קודם, ענף הוא רק מצביע מטלטלין להתחייבויות. בחלק זה, נחקור עבודה בענפים שונים: כיצד למזג שינויים מענף אחד לאחר, אילו קונפליקטים עלולים להיווצר ועוד. כדי לראות רשימה של כל הסניפים במאגר ולהבין באיזה מהם אתה נמצא, עליך לכתוב:
git branch -a

- צור סניף חדש על סמך זה שאנחנו נמצאים בו (99% מהמקרים)
- צור סניף על סמך התחייבות ספציפית (1% מהמקרים)
בואו ניצור סניף על סמך מחויבות ספציפית
אנו נסתמך על המזהה הייחודי של ההתחייבות. כדי למצוא אותו, אנו כותבים:
git log

git checkout -b development 6c44e53d06228f888f2f454d3cb8c1c976dd73f8
נוצר סניף עם שני המחויבויות הראשונות בלבד מהסניף הראשי. כדי לאמת זאת, תחילה אנו מקפידים לעבור לסניף אחר ולבחון את מספר ההתחייבויות שם:
git status
git log

git branch -a

בואו ניצור סניף על סמך הענף הנוכחי
הדרך השנייה ליצור ענף היא ליצור אותו מתוך אחר. אני רוצה ליצור סניף המבוסס על ענף המאסטר. ראשית, אני צריך לעבור אליו, והשלב הבא הוא ליצור אחד חדש. בואו נסתכל:- git checkout master — עבור לסניף המאסטר
- git status - ודא שאנחנו באמת בענף המאסטר

git checkout -b feature/update-txt-files

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

git add *.txt
git commit -m "updated txt files"
git log

git checkout master
git merge feature/update-txt-files
git log

git branch -D feature/update-txt-files
הכל ברור עד כה, כן? בואו נסבך את המצב: עכשיו נניח שאתה צריך לשנות שוב את קובץ ה-txt. אבל עכשיו הקובץ הזה ישתנה גם בענף המאסטר. במילים אחרות, זה ישתנה במקביל. Git לא תוכל להבין מה לעשות כשנרצה למזג את הקוד החדש שלנו לתוך ענף המאסטר. בוא נלך! אנו ניצור סניף חדש המבוסס על מאסטר, נבצע שינויים ב-text_resource.txt וניצור מחויבות לעבודה זו:
git checkout -b feature/add-header
... we make changes to the file

git add *.txt
git commit -m "added header to txt"

git checkout master
… we updated test_resource.txt

git add test_resource.txt
git commit -m "added master header to txt"
ועכשיו הנקודה המעניינת ביותר: אנחנו צריכים למזג שינויים מהענף של feature/add-header למאסטר. אנחנו בסניף המאסטר, אז אנחנו צריכים רק לכתוב:
git merge feature/add-header
אבל התוצאה תהיה התנגשות בקובץ test_resource.txt: 

- השינויים שהיו בשורה זו בענף המאסטר נמצאים בין "<<<<<<< HEAD" ו-"========".
- השינויים שהיו בענף feature/add-header נמצאים בין "=======" ו">>>>>>> feature/add-header".

git status

git add *.txt

git commit

עבודה עם מאגרים מרוחקים
השלב האחרון הוא להבין כמה פקודות נוספות הדרושות לעבודה עם המאגר המרוחק. כפי שאמרתי, מאגר מרוחק הוא מקום שבו המאגר מאוחסן וממנו ניתן לשכפל אותו. איזה סוג של מאגרים מרוחקים יש? דוגמאות:-
GitHub היא פלטפורמת האחסון הגדולה ביותר עבור מאגרים ופיתוח שיתופי. כבר תיארתי את זה במאמרים קודמים.
עקבו אחרי ב- GitHub . אני מרבה להשוויץ בעבודתי שם באותם תחומים שאני לומד לעבודה. -
GitLab הוא כלי מבוסס אינטרנט למחזור החיים של DevOps עם קוד פתוח . זוהי מערכת מבוססת Git לניהול מאגרי קוד עם ויקי משלה, מערכת מעקב אחר באגים , צינור CI/CD ופונקציות אחרות.
לאחר החדשות שמיקרוסופט קנתה את GitHub, כמה מפתחים שכפלו את הפרויקטים שלהם ב-GitLab. -
BitBucket הוא שירות אינטרנט לאירוח פרויקטים ופיתוח שיתופי המבוסס על מערכות בקרת גרסאות Mercurial ו-Git. פעם היה לו יתרון גדול על GitHub בכך שהוא הציע מאגרים פרטיים בחינם. בשנה שעברה, GitHub גם הציג את היכולת הזו לכולם בחינם.
-
וכולי…
git clone https://github.com/romankh3/git-demo
כעת יש עותק מקומי שלם של הפרויקט. כדי להיות בטוח שהעותק המקומי של הפרויקט הוא העדכני ביותר, עליך למשוך את הפרויקט על ידי כתיבה:
git pull


git add test_resource.txt
git commit -m "prepared txt for pushing"
הפקודה לדחוף את זה למאגר המרוחק היא:
git push

קישור שימושי
- תיעוד רשמי של Git . אני ממליץ על זה בתור התייחסות.
GO TO FULL VERSION