גל חדד MSc במערכות מידע

וורדפרס

וורדפרס

Git לפרילנסר וורדפרס: מ-zip ל-workflow אמיתי

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

המדריך הזה הוא על המעבר מ-zip ו-FTP ל-workflow מבוסס Git. הוא מסביר למה כל כלי קיים ומתי משתמשים בו, לא רק איך. אני עובד ככה יום-יום, וזו אחת ההשקעות שהחזירו את עצמן הכי מהר. בסוף המדריך יש גם שלוש מלכודות שכמעט כולם נופלים בהן פעם אחת, עדיף שתדעו עליהן מראש.

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

מה Git בעצם עושה

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

זה נותן לכם ארבעה דברים שה-zip לא נותן:

  • רשת ביטחון. שברתם משהו? חוזרים אחורה ל-commit תקין.
  • יומן עבודה. מה בדיוק שיניתם, לאיזה לקוח, ומתי.
  • ניסויים בלי פחד. ענפים (branches), שנגיע אליהם עוד מעט.
  • בסיס לדפלוי. ברגע שמתחברים ל-GitHub, אפשר לדחוף שינויים לשרת בפקודה אחת במקום להעלות zip.

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

להתקין את Git

לפני הכל צריך שיהיה לכם Git על המחשב. ההתקנה שונה בין מערכות ההפעלה.

  • macOS: הדרך הנקייה היא דרך Homebrew:
Terminal window
brew install git

אם אין לכם Homebrew, הקלדת git --version בטרמינל תציע להתקין את Xcode Command Line Tools, שכוללים גרסה של Git. שתי הדרכים תקינות; אני מעדיף Homebrew כי קל יותר לעדכן.

  • Windows: אני ממליץ לעבוד בתוך WSL2 (סביבת לינוקס בתוך Windows), כי שם הסביבה מתנהגת כמו השרת שאליו תעלו בסוף. בתוך טרמינל ה-WSL2:
Terminal window
sudo apt install git

אם אתם מעדיפים לעבוד ישירות ב-Windows בלי WSL2, יש את Git for Windows (להוריד מ-git-scm.com, או winget install Git.Git). זה עובד, אבל לכל אורך המדריך הזה אני מניח WSL2.

אחרי ההתקנה, Git צריך לדעת מי אתם (החתימה על כל commit):

Terminal window
git config --global user.name "Your Name"
git config --global user.email "you@example.com"
git config --global init.defaultBranch main

מודל החשיבה היחיד שחשוב

זה החלק שאם תבינו אותו, כל השאר מסתדר. לקובץ ב-Git יש שלושה אזורים:

Working Directory → Staging Area → Repository (.git)
(הקבצים האמיתיים) (מה ש-git add בחר) (תצלומים שנשמרו)
עורכים git add git commit

אתם עורכים קבצים ב-Working Directory. בוחרים אילו שינויים ייכנסו לתצלום הבא עם git add, זה מעביר אותם ל-Staging Area. ואז git commit מקפיא את מה שב-staging לתצלום קבוע ב-Repository (תיקיית .git הנסתרת).

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

הזרימה היומיומית נראית ככה:

Terminal window
git status # מה השתנה ומה ב-staging, הפקודה שתריצו הכי הרבה
git add . # מעביר את כל השינויים ל-staging
git commit -m "Add footer template"
git log --oneline # ההיסטוריה, שורה ל-commit
פלט git status שמראה קובץ ב-Working Directory וקובץ אחר כבר ב-staging, עם הצבעים של Git.

עוד שתי פקודות שתשתמשו בהן כל הזמן: git diff מראה מה השתנה ב-Working Directory ועדיין לא ב-staging, שורה-שורה, זו התשובה ל”מה אני עומד לעשות לו commit”. אחרי git add, השינוי כבר ב-staging, אז git diff רגיל יראה ריק; כדי לראות מה עומד להיכנס משתמשים ב-git diff --staged.

ענפים זולים, לעבוד בלי לפחד

זה החלק ששינה לי הכי הרבה את העבודה. branch הוא בסך הכל מצביע שזז ומראה על commit. יצירת branch לא מעתיקה קבצים; היא מיידית וכמעט בחינם.

למה זה משנה לפרילנסר: אתר הלקוח חי ועובד, ואתם רוצים לבנות פיצ’ר חדש. אתם לא רוצים קוד חצי-גמור על ה-branch הראשי (main). אז פותחים branch, עושים שם את כל ה-commits המבולגנים של עבודה בתהליך, ו-main נשאר נקי ובר-דפלוי כל הזמן. כשהפיצ’ר מוכן ונבדק, ממזגים בחזרה.

Terminal window
git switch -c feature-footer # יוצר branch ועובר אליו (-c = create)
# ... עורכים, git add, git commit ...
git switch main # חוזרים ל-main

git switch -c היא הפקודה המודרנית. ברחבי האינטרנט תיתקלו גם ב-git checkout -b, אותו דבר בדיוק.

שימו לב לדבר אחד שמבלבל בהתחלה: כשאתם עוברים בין branches, קבצים “נעלמים” ומופיעים. זה מכוון. מעבר branch משכתב את ה-Working Directory כך שיתאים לתצלום שה-branch מצביע עליו. הקבצים לא אבדו, הם שמורים בתוך ה-commits של ה-branch השני, ויחזרו ברגע שתחזרו אליו.

מיזוג, ושני סוגי merge

כשהפיצ’ר מוכן, ממזגים אותו חזרה ל-main:

Terminal window
git switch main
git merge feature-footer

יש כאן שני תרחישים, וכדאי להכיר את שניהם כי הפלט נראה שונה:

  • Fast-forward. אם main לא זז מאז שפתחתם את ה-branch, אין מה לשלב, Git פשוט מחליק את המצביע main קדימה כדי להדביק את ה-branch. בלי merge commit חדש.
  • Merge commit. אם גם main וגם ה-branch קיבלו commits חדשים, אי אפשר להחליק. Git יוצר merge commit שמשלב את שתי ההיסטוריות. זה ה-commit היחיד עם שני הורים, וזו הדרך של Git לתעד “כאן שני קווי עבודה התאחדו”.

מיזוג של קבצים שונים עובר אוטומטית. הכאב מתחיל כששני branches שינו את אותה שורה באותו קובץ, אז מקבלים merge conflict. זו לא שגיאה; Git פשוט אומר “שניכם שיניתם את אותו מקום, תחליטו אתם”. הקובץ יכיל סמנים:

<<<<<<< HEAD
# הגרסה שלי
=======
# הגרסה הנכנסת
>>>>>>> feature-title

הפתרון פשוט גם אם הוא נראה מאיים: עורכים את הקובץ לטקסט הסופי הרצוי, מוחקים את כל שלושת הסמנים (<<<<<<<, =======, >>>>>>>), ואז:

Terminal window
git add README.md # אומר ל-Git "פתרתי את הקונפליקט"
git commit -m "Merge feature-title"

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

כשמשהו משתבש, לתקן טעויות

אין ב-Git כפתור “undo” אחד. הפקודה תלויה באיפה הטעות נמצאת כרגע. הנה המפה:

  • שינוי לא-שמור שאתם רוצים לזרוק: git restore <file> מחזיר את הקובץ למצב ה-commit האחרון. זו פקודה הרסנית: השינוי הלא-שמור נמחק. רק כשאתם בטוחים שהוא זבל.
  • הכנסתם קובץ ל-staging בטעות: git restore --staged <file> מוציא אותו מ-staging, אבל התוכן נשאר.
  • ה-commit האחרון שגוי (הודעה לא נכונה, או שכחתם קובץ), git commit --amend. זה מחליף את ה-commit האחרון ב-commit חדש.
  • commit ישן שאתם רוצים לבטל: כאן יש שתי פקודות, וההבדל ביניהן קריטי. נחזור אליו בעוד רגע ב”מלכודות”.

ועוד אחת ששווה זהב: git stash. אתם באמצע פיצ’ר, הקוד עוד לא בשל ל-commit, ולקוח צריך תיקון דחוף ב-main. אי אפשר להחליף branch עם שינויים פתוחים. אז:

Terminal window
git stash # מדף את השינויים בצד, ה-Working Directory נקי
git switch main # מטפלים בדחוף
git switch feature-x
git stash pop # מחזירים את העבודה למקום

להתחבר ל-GitHub

עד עכשיו הכל היה מקומי. GitHub הוא שירות אירוח ל-repos של Git: גיבוי בענן, גישה מכל מקום, ובסיס לדפלוי. Git הוא הכלי לניהול הגרסאות; GitHub הוא שירות שמאחסן repos של Git בענן.

מחברים repo מקומי ל-GitHub בשלושה צעדים:

Terminal window
gh repo create my-project --private # יוצר repo ריק ב-GitHub
git remote add origin https://github.com/you/my-project.git
git push -u origin main # דוחפים את כל ה-commits

remote הוא סימנייה בעלת שם לעותק של ה-repo שמתארח במקום אחר. המוסכמה היא לקרוא לראשי origin. ה--u בדחיפה הראשונה אומר ש-main המקומי עוקב אחרי origin/main, ומכאן והלאה אפשר סתם git push ו-git pull בלי ארגומנטים.

עכשיו נקודה שמבלבלת המון אנשים, ושווה להבין לעומק. ה-repo המקומי שלכם שומר מצביע בשם origin/main, תמונת מצב של “איפה main של GitHub היה בפעם האחרונה שבדקתי”. המצביע הזה תקוע ולא מתעדכן לבד, גם אם מישהו דחף שינויים ל-GitHub. הוא זז רק כשאתם פונים לשרת. מכאן ההבדל בין שתי פקודות:

git fetch → מוריד commits חדשים מ-GitHub ומעדכן את origin/main. לא נוגע בקבצים שלכם.
git pull → git fetch + git merge. מוריד וגם ממזג ל-branch הנוכחי.

fetch אומר “תן לי לראות מה חדש בלי להפריע לעבודה”. pull אומר “תוריד ותחיל מיד”. pull הוא בדיוק fetch ואז merge בצעד אחד. אני נוטה ל-git fetch קודם כשאני לא בטוח מה קרה בצד השני, מסתכל מה ירד, ורק אז מחליט אם למזג.

ולהתחיל עבודה על פרויקט קיים (או על מחשב חדש) זה פשוט git clone <url>, זה מוריד את כל ההיסטוריה ומגדיר את origin אוטומטית.

Pull Request, גם כשאתם לבד

Pull Request (PR) הוא בקשה למזג branch אחד לתוך אחר, עטופה בעמוד GitHub שבו רואים את ה-diff, מריצים בדיקות אוטומטיות, ולוחצים merge. זה merge מנוהל עם שלב סקירה.

“רגע, אני עובד לבד, למה לי PR?” שאלה הוגנת, וגם אני שאלתי אותה. התשובה: PR נותן לכם שני דברים גם בעבודת סולו. ראשית, משמעת, אתם מסתכלים על ה-diff המלא לפני שמשהו נכנס ל-main, וזה תופס שטויות. שנית, שער, אפשר להגדיר ב-GitHub branch protection שחוסם push ישיר ל-main ומחייב שבדיקות אוטומטיות יעברו לפני merge. כש-main הוא ה-branch שעולה לפרודקשן, השער הזה שווה הרבה.

Terminal window
git switch -c feature-about
git add . && git commit -m "Add about page"
git push -u origin feature-about # דוחפים את ה-BRANCH, לא את main
gh pr create --base main --head feature-about --title "Add about page"
gh pr merge --merge --delete-branch # ממזג ומנקה את ה-branch בשני הצדדים
עמוד ה-PR ב-GitHub עם ה-diff בפורמט הירוק/אדום, לפני לחיצת ה-merge.

שלוש המלכודות שכולם נופלים בהן

שלוש הטעויות האלה הן הסיבה שכתבתי את המדריך, ראיתי אותן אצל כל מי שעבר ל-Git, ואצל עצמי בהתחלה.

1. ה-.env שכבר נכנס ל-commit

בפרויקט וורדפרס יש דברים שאסור שייכנסו ל-repo: סודות (סיסמת DB, מפתחות API ב-.env), תלויות שאפשר להוריד מחדש (vendor/, node_modules/), ומדיה שהועלתה. בשביל זה יש את .gitignore, קובץ טקסט עם רשימת patterns ש-Git יתעלם מהם:

.env
/vendor/
/node_modules/
.DS_Store
*.log

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

Terminal window
git rm --cached .env # מפסיק לעקוב, בלי למחוק את הקובץ עצמו
git commit -m "Stop tracking .env"

הכלל שיחסוך לכם את כל הסיפור: כתבו את .gitignore לפני ה-git add הגדול הראשון.

2. case-sensitivity שעובד אצלכם ושובר בייצור

זו אחת המלכודות הכי מבאסות, כי היא לא מתפוצצת אצלכם, היא מתפוצצת בשרת. ה-filesystem של macOS ושל Windows הוא case-insensitive: בשבילם Header.php ו-header.php הם אותו קובץ. אבל Git עושה התאמת נתיבים משלו וכן אכפת לו מהאותיות, וגם השרת בייצור (Linux) רגיש לאותיות.

התרחיש הקלאסי: רשמתם בקוד require 'Header.php' אבל הקובץ נשמר כ-header.php. אצלכם זה עובד מצוין. מעלים לשרת, והאתר נשבר עם שגיאת “file not found”, על קובץ שאתם רואים בעיניים שקיים. תהיו עקביים באותיות בשמות קבצים, ובהפניות אליהם בקוד. כשעובדים ב-WSL2 ב-Windows אתם קרובים יותר להתנהגות של השרת, וזו עוד סיבה לעבוד שם.

3. reset מול revert, מתי כל אחד

שתי הפקודות מבטלות commit, אבל בדרך הפוכה לגמרי, וההבדל קריטי:

  • git reset מזיז את מצביע ה-branch אחורה ובכך משכתב היסטוריה. נהדר לטעויות מקומיות שעוד לא דחפתם. שימוש נפוץ: git reset --mixed HEAD~1 (“התחרטתי על ה-commit האחרון, אעשה אותו מחדש”). יש גם --hard, שמוחק גם את השינויים עצמם, זה היחיד שמשמיד עבודה, אז זהירות.
  • git revert לא מוחק כלום. הוא יוצר commit חדש שהוא ההיפוך של היעד, מבטל את השינוי ומשאיר את ההיסטוריה שלמה.
Terminal window
git reset --mixed HEAD~1 # מקומי: מבטל commit, השינויים חוזרים ל-working dir
git revert HEAD --no-edit # משותף: יוצר commit חדש שמבטל את הקודם

הכלל במשפט אחד: reset לטעויות מקומיות שעוד לא דחפתם; revert לכל מה שכבר נמצא ב-GitHub. אם תשכתבו היסטוריה שכבר שיתפתם, תשברו אותה לכל מי שמשך אותה, כולל לשרת. זה כל המשחק.

איך זה נראה ביום-יום

אחרי שכל החלקים במקום, הלולאה שאני עובד בה על כל פרויקט נראית ככה:

Terminal window
1. git switch -c feature/x # branch לכל משימה
2. work, commit in small steps # כל commit = שינוי לוגי אחד
3. git push -u origin feature/x # דוחפים את ה-branch
4. open a PR # סוקרים את ה-diff
5. merge PR main # main תמיד בר-דפלוי

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

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


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

תגובות

טוען תגובות…

השארת תגובה

התגובות עוברות אישור לפני הפרסום.

להישאר בקשר

פעם בכמה שבועות אני שולח מכתב אחד: מה למדתי, מה בניתי, ומה שווה את הזמן שלכם בעולם ה־AI. בלי ספאם, בלי מכירות.

אפשר לבטל בכל רגע, בקליק אחד.