וורדפרס
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:
brew install gitאם אין לכם Homebrew, הקלדת git --version בטרמינל תציע להתקין את Xcode Command Line Tools, שכוללים גרסה של Git. שתי הדרכים תקינות; אני מעדיף Homebrew כי קל יותר לעדכן.
- Windows: אני ממליץ לעבוד בתוך WSL2 (סביבת לינוקס בתוך Windows), כי שם הסביבה מתנהגת כמו השרת שאליו תעלו בסוף. בתוך טרמינל ה-WSL2:
sudo apt install gitאם אתם מעדיפים לעבוד ישירות ב-Windows בלי WSL2, יש את Git for Windows (להוריד מ-git-scm.com, או winget install Git.Git). זה עובד, אבל לכל אורך המדריך הזה אני מניח WSL2.
אחרי ההתקנה, Git צריך לדעת מי אתם (החתימה על כל commit):
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, במקום שהכל יישמר בערימה אחת. זה מה שהופך את ההיסטוריה לקריאה אחר כך.
הזרימה היומיומית נראית ככה:
git status # מה השתנה ומה ב-staging, הפקודה שתריצו הכי הרבהgit add . # מעביר את כל השינויים ל-staginggit commit -m "Add footer template"git log --oneline # ההיסטוריה, שורה ל-commitעוד שתי פקודות שתשתמשו בהן כל הזמן: git diff מראה מה השתנה ב-Working Directory ועדיין לא ב-staging, שורה-שורה, זו התשובה ל”מה אני עומד לעשות לו commit”. אחרי git add, השינוי כבר ב-staging, אז git diff רגיל יראה ריק; כדי לראות מה עומד להיכנס משתמשים ב-git diff --staged.
ענפים זולים, לעבוד בלי לפחד
זה החלק ששינה לי הכי הרבה את העבודה. branch הוא בסך הכל מצביע שזז ומראה על commit. יצירת branch לא מעתיקה קבצים; היא מיידית וכמעט בחינם.
למה זה משנה לפרילנסר: אתר הלקוח חי ועובד, ואתם רוצים לבנות פיצ’ר חדש. אתם לא רוצים קוד חצי-גמור על ה-branch הראשי (main). אז פותחים branch, עושים שם את כל ה-commits המבולגנים של עבודה בתהליך, ו-main נשאר נקי ובר-דפלוי כל הזמן. כשהפיצ’ר מוכן ונבדק, ממזגים בחזרה.
git switch -c feature-footer # יוצר branch ועובר אליו (-c = create)# ... עורכים, git add, git commit ...git switch main # חוזרים ל-maingit switch -c היא הפקודה המודרנית. ברחבי האינטרנט תיתקלו גם ב-git checkout -b, אותו דבר בדיוק.
שימו לב לדבר אחד שמבלבל בהתחלה: כשאתם עוברים בין branches, קבצים “נעלמים” ומופיעים. זה מכוון. מעבר branch משכתב את ה-Working Directory כך שיתאים לתצלום שה-branch מצביע עליו. הקבצים לא אבדו, הם שמורים בתוך ה-commits של ה-branch השני, ויחזרו ברגע שתחזרו אליו.
מיזוג, ושני סוגי merge
כשהפיצ’ר מוכן, ממזגים אותו חזרה ל-main:
git switch maingit 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הפתרון פשוט גם אם הוא נראה מאיים: עורכים את הקובץ לטקסט הסופי הרצוי, מוחקים את כל שלושת הסמנים (<<<<<<<, =======, >>>>>>>), ואז:
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 עם שינויים פתוחים. אז:
git stash # מדף את השינויים בצד, ה-Working Directory נקיgit switch main # מטפלים בדחוףgit switch feature-xgit stash pop # מחזירים את העבודה למקוםלהתחבר ל-GitHub
עד עכשיו הכל היה מקומי. GitHub הוא שירות אירוח ל-repos של Git: גיבוי בענן, גישה מכל מקום, ובסיס לדפלוי. Git הוא הכלי לניהול הגרסאות; GitHub הוא שירות שמאחסן repos של Git בענן.
מחברים repo מקומי ל-GitHub בשלושה צעדים:
gh repo create my-project --private # יוצר repo ריק ב-GitHubgit remote add origin https://github.com/you/my-project.gitgit push -u origin main # דוחפים את כל ה-commitsremote הוא סימנייה בעלת שם לעותק של ה-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 שעולה לפרודקשן, השער הזה שווה הרבה.
git switch -c feature-aboutgit add . && git commit -m "Add about page"git push -u origin feature-about # דוחפים את ה-BRANCH, לא את maingh pr create --base main --head feature-about --title "Add about page"gh pr merge --merge --delete-branch # ממזג ומנקה את ה-branch בשני הצדדיםשלוש המלכודות שכולם נופלים בהן
שלוש הטעויות האלה הן הסיבה שכתבתי את המדריך, ראיתי אותן אצל כל מי שעבר ל-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 ימשיך לעקוב אחריו והסוד שלכם יישאר בהיסטוריה. הפתרון הוא להפסיק לעקוב ידנית:
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 חדש שהוא ההיפוך של היעד, מבטל את השינוי ומשאיר את ההיסטוריה שלמה.
git reset --mixed HEAD~1 # מקומי: מבטל commit, השינויים חוזרים ל-working dirgit revert HEAD --no-edit # משותף: יוצר commit חדש שמבטל את הקודםהכלל במשפט אחד: reset לטעויות מקומיות שעוד לא דחפתם; revert לכל מה שכבר נמצא ב-GitHub. אם תשכתבו היסטוריה שכבר שיתפתם, תשברו אותה לכל מי שמשך אותה, כולל לשרת. זה כל המשחק.
איך זה נראה ביום-יום
אחרי שכל החלקים במקום, הלולאה שאני עובד בה על כל פרויקט נראית ככה:
1. git switch -c feature/x # branch לכל משימה2. work, commit in small steps # כל commit = שינוי לוגי אחד3. git push -u origin feature/x # דוחפים את ה-branch4. open a PR # סוקרים את ה-diff5. merge PR → main # main תמיד בר-דפלויזה נשמע כמו הרבה, אבל אחרי שבוע זה אוטומטי לחלוטין, ואתם מקבלים יומן עבודה מלא, רשת ביטחון מדויקת, ובסיס לדפלוי מסודר. main תמיד נקי; כל הבלגן חי על branches.
זה הצעד הראשון לקראת עבודה כמו מפתח וורדפרס מודרני. הצעד הבא הוא לחבר את ה-workflow הזה לדפלוי אמיתי, שם Git מפסיק להיות נוחות והופך למנגנון שמעלה אתרים לאוויר. את זה אכסה במדריך נפרד.
אהבתם את ההסתכלות הזו על וורדפרס? אני שולח מדריכים פרקטיים כאלה, על וורדפרס, פיתוח ב-AI וחוויית משתמש, ישר לרשימת התפוצה. בלי ספאם, בלי פופאפים. הצטרפו לרשימה.
תגובות
טוען תגובות…