# Version Control: למה צריך, ומושגי היסוד של Git<no value>

## מה נלמד?

- מהי **Version Control** (בקרת גרסאות), ולמה כל מפתח משתמש בה.
- מהו **Git**.
- שלושת האזורים: **Working Directory**, **Staging Area**, **Repository**.
- מהו **Commit**.
- הגדרה ראשונית של Git.

## למה צריך את זה?

מכירים את התיקייה הזו?

```text
project_final.py
project_final_v2.py
project_final_v2_WORKS.py
project_final_v3_dont_touch.py
project_final_v3_fixed_REALLY_FINAL.py
```

הבעיות:

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

**Version Control** פותרת את כל אלה. בכל חברת תוכנה בעולם, כל שורת קוד מנוהלת בה. בלי Git, אי אפשר לעבוד בצוות פיתוח, ובראיון עבודה מצפים שתכירו אותו.

## הסבר מהבסיס

### מהי Version Control?

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

### מהו Git?

**Git** היא מערכת בקרת הגרסאות הנפוצה בעולם, בפער עצום. היא:

- **מקומית** — כל ההיסטוריה שמורה **אצלכם במחשב**, בתיקייה נסתרת `.git`. עובד גם בלי אינטרנט.
- **מבוזרת** (Distributed) — לכל מפתח יש עותק **מלא** של כל ההיסטוריה.
- **מהירה וחינמית**, וכתובה במקור על ידי לינוס טורבאלדס, יוצר Linux.

**Git ≠ GitHub!** Git הוא **הכלי** שרץ אצלכם. **GitHub** הוא **אתר** שמאחסן עותק של ה-Repository שלכם בענן, ומוסיף כלים לשיתוף ולעבודת צוות. נכיר אותו בשיעור השלישי.

### Repository (מאגר)

**Repository** (בקיצור **Repo**) = פרויקט ש-Git עוקב אחריו: התיקייה עם הקבצים, **ועוד** התיקייה הנסתרת `.git` שבה שמורה כל ההיסטוריה.

### Commit — תמונת מצב

**Commit** = **תמונת מצב** (Snapshot) שמורה של הפרויקט ברגע מסוים, עם:

- **הודעה** שמסבירה מה השתנה ולמה.
- **מחבר** (שם ומייל) ו**זמן**.
- **מזהה ייחודי** (Hash), למשל `a3f9c21`.
- הפניה ל-Commit **הקודם**, וכך נוצרת **שרשרת** היסטוריה.

```text
(a3f9c21) ◄── (7b2e004) ◄── (e91d5aa)   ← HEAD (latest)
"Initial      "Add price     "Fix VAT
 project"      calculator"    rounding"
```

{{< box "analogy" "אנלוגיה: נקודות שמירה במשחק" >}}
**Commit** = נקודת שמירה במשחק מחשב. לפני הקרב עם הבוס שומרים. אם מפסידים, חוזרים לנקודה. ההבדל: ב-Git **כל** נקודת שמירה נשארת לתמיד, עם תיאור, ואפשר לחזור לכל אחת מהן או להשוות ביניהן.
{{< /box >}}

### שלושת האזורים

זה המושג החשוב ביותר בשיעור. כל קובץ בפרויקט נמצא באחד משלושה "אזורים":

```text
 Working Directory        Staging Area            Repository (.git)
 (the files you edit)     (ready for the next     (committed history)
                           commit)
       │                        │                        │
       │──── git add ──────────►│                        │
       │                        │──── git commit ───────►│
       │◄──────────────────── (checkout / restore) ──────│
```

| אזור | מה זה | איך מגיעים אליו |
|---|---|---|
| **Working Directory** | התיקייה שאתם עובדים בה: הקבצים כמו שהם עכשיו בדיסק | פשוט עורכים קבצים |
| **Staging Area** (נקרא גם Index) | "אזור הכנה": השינויים שבחרתם להכניס ל-Commit **הבא** | `git add` |
| **Repository** | ההיסטוריה השמורה: כל ה-Commits | `git commit` |

**למה צריך Staging?** כי לפעמים שיניתם 5 קבצים, אבל רק 3 מהם שייכים לאותו שינוי לוגי ("תיקון באג במחשבון"). Staging מאפשר לבחור **בדיוק** מה נכנס לכל Commit, כך שכל Commit הוא יחידה הגיונית אחת.

{{< box "analogy" "אנלוגיה: צילום תמונה קבוצתית" >}}
**Working Directory** = כל האנשים באירוע. **Staging Area** = האנשים שהזמנתם לעמוד מול המצלמה ("בואו, אתם, לתמונה"). **Commit** = לחיצה על הכפתור: התמונה נשמרת באלבום (Repository) לתמיד. מי שלא עמד מול המצלמה לא נכנס לתמונה, גם אם הוא באירוע.
{{< /box >}}

### מצבי קבצים

| מצב | משמעות |
|---|---|
| **Untracked** | קובץ חדש ש-Git עוד לא עוקב אחריו |
| **Modified** | קובץ מוכר ששונה מאז ה-Commit האחרון, אבל עוד לא ב-Staging |
| **Staged** | השינוי ב-Staging, ומוכן ל-Commit |
| **Committed** (Unmodified) | זהה ל-Commit האחרון, "נקי" |

## תחביר

**התקנה:** Git הותקן ביום הראשון של הקורס. בודקים: `git --version`.

**הגדרה חד-פעמית** (פעם אחת למחשב). Git רושם את השם והמייל בכל Commit:

```powershell
git config --global user.name "Dana Cohen"
git config --global user.email "dana@example.com"
git config --global init.defaultBranch main
git config --global core.editor "code --wait"
```

| פקודה | משמעות |
|---|---|
| `user.name` / `user.email` | מי כתב את ה-Commit. בשיעור 3, אותו מייל כמו בחשבון ה-GitHub. |
| `init.defaultBranch main` | שם הענף הראשי יהיה `main` (המוסכמה המודרנית). |
| `core.editor "code --wait"` | אם Git צריך לפתוח עורך, יפתח VS Code. |
| `--global` | ההגדרה חלה על כל הפרויקטים במחשב. |

**בדיקה:**

```powershell
git config --global --list
```

## דוגמת קוד ראשונה

נראה את רעיון ה"שלושה אזורים" בפקודות. בשיעור הבא נפרק כל אחת לעומק.

```powershell
mkdir ~\dev\kodkod6\git-demo
cd ~\dev\kodkod6\git-demo
git init
```

**פלט:**

```text
Initialized empty Git repository in C:/Users/dana/dev/kodkod6/git-demo/.git/
```

עכשיו יש Repository. התיקייה הנסתרת `.git` נוצרה. אפשר לראות אותה עם `ls -Force` (PowerShell) או `ls -a` (Bash).

## פירוק הקוד שורה אחר שורה

| שורה | הסבר |
|---|---|
| `mkdir ...git-demo` | תיקייה רגילה לפרויקט. |
| `cd ...git-demo` | נכנסים אליה. **כל פקודות Git פועלות על ה-Repository של התיקייה הנוכחית.** |
| `git init` | **init**ialize: הופך את התיקייה ל-Repository, ויוצר בתוכה את `.git`. |
| `.git/` | "המוח" של ה-Repository: כל ה-Commits, ההיסטוריה וההגדרות. **לא נוגעים בה ידנית.** אם מוחקים אותה, כל ההיסטוריה נמחקת (הקבצים עצמם נשארים). |

## דוגמה נוספת

**מסע של שינוי אחד, דרך שלושת האזורים**, עם `git status` אחרי כל צעד (הפירוט המלא בשיעור הבא):

```powershell
New-Item hello.py
git status
git add hello.py
git status
git commit -m "Add hello.py"
git status
```

**פלט (מקוצר):**

```text
Untracked files:
        hello.py

Changes to be committed:
        new file:   hello.py

[main (root-commit) 3c1f2a9] Add hello.py
 1 file changed, 0 insertions(+), 0 deletions(-)

nothing to commit, working tree clean
```

| שלב | מצב `hello.py` | אזור |
|---|---|---|
| אחרי `New-Item` | **Untracked** | Working Directory בלבד |
| אחרי `git add` | **Staged** | Staging Area |
| אחרי `git commit` | **Committed**, ו-"working tree clean" | Repository |

## טעות נפוצה

**הטעות 1: `git init` בתיקייה הלא נכונה**, למשל בתיקיית הבית (`C:\Users\dana`) או בתוך תיקייה שכבר נמצאת בתוך Repository אחר. אז Git עוקב אחרי **כל** הקבצים במחשב, או שנוצרים Repositories מקוננים ומבלבלים.

**תמיד:** `cd` לתיקיית הפרויקט, `pwd` כדי לוודא, ורק אז `git init`. ואם טעיתם: מוחקים את התיקייה הנסתרת `.git` שנוצרה בטעות (רק אותה!).

**הטעות 2: "עשיתי `git add`, אז זה שמור."** לא! `add` רק מכין. רק **`commit`** שומר בהיסטוריה. ושינוי שעשיתם **אחרי** ה-`add` לא נכלל, עד שתעשו `add` שוב.

**הטעות 3: לחשוב ש-Git מגבה בענן.** Git מקומי. אם הלפטופ אבד, ה-Repository אבד איתו, אלא אם עשיתם **push** ל-GitHub (שיעור 3).

**הטעות 4: לא להגדיר `user.name` / `user.email`.**

```text
Author identity unknown
*** Please tell me who you are.
```

Git מסרב לבצע Commit בלי לדעת מי המחבר. מריצים את פקודות ה-`config` מלמעלה.

<!-- exercises:start — generated by scripts/intro6/sync_site_exercises.py; edit scripts/intro6/exercises/ -->
## תרגול

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

### תרגיל 1: למה צריך ניהול גרסאות?

בתיקייה של דני יש את הקבצים:

```text
project_final.py
project_final_v2.py
project_final_v2_WORKS.py
project_final_v3_dont_touch.py
```

תנו שלוש בעיות בשיטה הזו, ואיך Git פותר כל אחת.

{{< solution >}}
| הבעיה | איך Git פותר |
|---|---|
| לא ברור מה ההבדל בין הקבצים ומה השתנה בכל אחד | כל **Commit** שומר בדיוק מה השתנה, עם הודעה שמסבירה למה |
| אי אפשר לדעת איזו גרסה היא באמת האחרונה ועובדת | יש היסטוריה מסודרת אחת, ו-**HEAD** מצביע על המצב הנוכחי |
| כשעובדים כמה אנשים, כל אחד מוסיף "עוד גרסה" | כולם עובדים על אותו **Repository**, ו-Git יודע לחבר את השינויים |
{{< /solution >}}

### תרגיל 2: שלושת האזורים

לכל פעולה — באיזה אזור נמצא השינוי אחריה: Working Directory, Staging Area או Repository?

1. ערכתם את `calculator.py` ושמרתם.
2. הרצתם `git add calculator.py`.
3. הרצתם `git commit -m "Add subtract"`.

{{< solution >}}
1. **Working Directory** — השינוי קיים רק בקובץ על הדיסק.
2. **Staging Area** — השינוי סומן כחלק מה-Commit הבא.
3. **Repository** — השינוי נשמר כצילום מצב בהיסטוריה.
{{< /solution >}}

### תרגיל 3: הגדרה ראשונה

כתבו את הפקודות שמגדירות ל-Git את השם `Dana Cohen` ואת האימייל `dana@example.com`, ואז יוצרות Repository חדש בתיקייה הנוכחית. למה Git צריך שם ואימייל?

{{< solution >}}
```powershell
git config --global user.name "Dana Cohen"
git config --global user.email "dana@example.com"
git init
```

Git רושם בכל Commit **מי** ביצע אותו. בלי שם ואימייל, Git לא יסכים לבצע Commit. `--global` שומר את ההגדרה פעם אחת לכל ה-Repositories במחשב.
{{< /solution >}}

### תרגיל 4: שרשרת של Commits

```text
(a3f9c21) <── (7b2e004) <── (e91d5aa)  <- HEAD
"Initial      "Add price     "Fix VAT
 project"      calculator"    rounding"
```

1. מה זה כל אחד מהמזהים `a3f9c21`, `7b2e004`, `e91d5aa`?
2. על מה מצביע HEAD?
3. למה כל Commit "מצביע" על הקודם לו?

{{< solution >}}
1. אלה **מזהים של Commits** — כל Commit מקבל מזהה ייחודי (כאן מקוצר).
2. **HEAD** מצביע על ה-Commit הנוכחי — `e91d5aa`, "Fix VAT rounding". זה המצב שבו הקבצים נמצאים עכשיו.
3. כך נוצרת **היסטוריה**: מכל Commit אפשר ללכת אחורה ולראות מה היה לפניו, ולחזור לכל נקודה בעבר.
{{< /solution >}}

### תרגיל 5: למה צריך Staging Area?

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

{{< solution >}}
ה-Staging Area מאפשר **לבחור** מה ייכנס לכל Commit:

1. `git add calculator.py` → Commit: "Fix rounding bug in calculator".
2. `git add README.md` → Commit: "Improve README".
3. את קובץ הבדיקה הזמני לא מוסיפים בכלל.

כך כל Commit הוא **שינוי לוגי אחד** עם הודעה ברורה — ולא ערבוב של כל מה שנגעתם בו באותו יום.
{{< /solution >}}

<!-- exercises:end -->

## סיכום

- **Version Control** מתעדת כל שינוי, ומאפשרת לחזור אחורה, להשוות ולעבוד בצוות. **Git** הוא הכלי. **GitHub** הוא האתר שמאחסן בענן.
- **Repository** = פרויקט + התיקייה הנסתרת `.git` עם כל ההיסטוריה.
- **Commit** = תמונת מצב עם הודעה, מחבר, זמן ומזהה (Hash).
- שלושה אזורים: **Working Directory** → (`git add`) → **Staging Area** → (`git commit`) → **Repository**.
- הגדרה חד-פעמית: `git config --global user.name` / `user.email`.

<!-- docs:start — generated by scripts/intro6/site_docs.py; edit the links there -->

## דוקומנטציה רשמית

- [Pro Git — About Version Control](https://git-scm.com/book/en/v2/Getting-Started-About-Version-Control) — למה צריך ניהול גרסאות
- [Pro Git — What is Git?](https://git-scm.com/book/en/v2/Getting-Started-What-is-Git%3F) — Snapshots ושלושת המצבים
- [Pro Git — First-Time Git Setup](https://git-scm.com/book/en/v2/Getting-Started-First-Time-Git-Setup) — git config

<!-- docs:end -->
