עצי עבודה של Git לעבודה על כמה ענפים במקביל
המקור באנגלית פורסם ב־2026-05-16T20:16:22.751+03:00. המאמר המקורי באנגלית
מהדורה לימודית מתוקנת. תאריך הבדיקה הטכנית מול מקורות ראשוניים: 2026-10-28. דוגמאות הקוד לא הודרו ולא נבדקו בזמן ריצה. תאריך הפרסום המקורי באנגלית נשמר; המהדורה בעברית משתמשת בתאריך הפרסום שלה בפועל, ולא בתאריך המקור באנגלית.
עבודה על כמה ענפים
בו־זמנית
git worktree add ../feature
- main
- feature-auth
- hotfix-ssl
תכונת Git מתקדמת · פיתוח מקביל · הפרדת ענפים
התרשים המקורי (רשות, מוגדל)
התרשים המוגדל הוא תצוגת רשות. במידת הצורך אפשר לגלול אופקית או אנכית בתוך אזור זה; גרסת הטקסט הקריאה שמעליו כוללת את אותן תוויות ואת אותם קשרים בין הענפים.
עצי עבודה של Git
עבודה על כמה ענפים בתיקיות נפרדות, תוך צמצום הצורך ב־stash או בהחלפת עותק העבודה הנוכחי מקור
בו־זמנית
stash
בין עצי העבודה
מאז גרסה 2.5
מבוא: הבעיה שעצי עבודה של Git פותרים
תרחיש נפוץ הוא עבודה באמצע מימוש תכונה בענף feature/auth-refactor, ופתאום מגיעה הודעה: ״תקלה קריטית בסביבת הייצור, צריך תיקון בדחיפות!״ עומדות בפניכם שתי אפשרויות:
- לשמור את השינויים ב־stash, להחליף ענף, לתקן את התקלה, ליצור commit, לדחוף, לחזור לענף המקורי ולשלוף את ה־stash, בתקווה שלא יהיו התנגשויות
- לשכפל שוב את המאגר כולו לתיקייה שנייה ולעבוד במקביל
שתי האפשרויות מסורבלות. עצי עבודה של Git מספקים פתרון מובנה ונוח: אפשר לבצע checkout לכמה ענפים בו־זמנית בתיקיות נפרדות, החולקות את אותו מאגר .git ואת אותה היסטוריה.
🗂️ איך פועלים עצי עבודה
src/
package.json
ענף: main
src/ (גרסאות התיקון הדחוף)
ענף: hotfix/critical-fix
src/ (גרסאות התכונה)
ענף: feature/new-ui
עצי עבודה מקושרים חולקים את מאגר האובייקטים ואת רוב ההפניות, אך לכל אחד HEAD ואינדקס משלו. קובצי העבודה אינם משתקפים אוטומטית זה בזה. תיקיית Git המשותפת היא בדרך כלל .git של עץ העבודה הראשי. מקור
פקודות בסיסיות
מנהלים עצי עבודה באמצעות פקודות git worktree. אלה הפקודות העיקריות:
# Illustrative commands: not executed or runtime-tested.
# Choose one operation at a time in an authorized test repository.
# Existing branch (must not already be checked out elsewhere):
git worktree add ../my-repo-hotfix hotfix/critical-bug
# Or create a different worktree and a new branch from local main:
git worktree add -b feature/new-payment ../my-repo-payment main
# Detached review of a real commit; replace COMMIT_SHA with a verified hash:
git worktree add --detach ../my-repo-review COMMIT_SHA
# Inspect registered worktrees:
git worktree list
# Illustrative paths/commit abbreviations, not actual command output:
# /home/example/my-repo a1b2c3d [main]
# /home/example/my-repo-hotfix b2c3d4e [hotfix/critical-bug]
# Inspect and preserve work before removal; run outside the target directory:
git -C ../my-repo-hotfix status --short
git worktree remove ../my-repo-hotfix
# If removal refuses, inspect the cause. Do not add --force automatically.
# Preview stale administrative records, then prune only after inspection:
git worktree prune --dry-run
# git worktree prune
# Alternative operation for a STILL-EXISTING worktree (not after removing it):
# Ensure the destination parent exists and the target is not in use.
# git worktree move ../my-repo-hotfix ../archives/hotfix-exampleדוגמה מעשית: תיקון דחוף בלי לפגוע בעבודה על תכונה
# Bash workflow outline; runtime-untested, not a single paste-and-run script.
# Begin in the feature worktree; choose unused absolute paths.
cd "$HOME/my-repo" || exit 1
repo=$(git rev-parse --show-toplevel) || exit 1
hotfix="$HOME/my-repo-hotfix"
# local main must be an appropriate, verified base for this fix.
git worktree add -b hotfix/login-null-check "$hotfix" main || exit 1
cd "$hotfix" || exit 1
# Edit only the intended file, inspect, then commit and push when authorized:
vim src/auth/login.ts
git diff -- src/auth/login.ts
git add -- src/auth/login.ts
git commit -m "fix: handle null user on login redirect"
git push origin hotfix/login-null-check
# STOP: create/review/merge the PR through the repository's normal process.
# Do not additionally merge or push main locally after a remote PR merge.
# Only after confirming the PR is merged and the hotfix worktree is no longer needed:
cd "$repo" || exit 1
git -C "$hotfix" status --short
git worktree remove "$hotfix" # refuses unsafe removal; inspect any refusal
# Optional: after verifying reachability of its commits in the relevant branch:
# git branch -d hotfix/login-null-check
# A squash/rebase merge may cause -d to refuse. Do not force-delete blindly.
# The original feature worktree was not switched or reset.שימוש מתקדם: CI/CD, סקירות קוד ובדיקות מקבילות
# Independent Bash patterns; all runtime-untested.
# Trusted repository code only: tests/builds can execute scripts.
repo=$(git rev-parse --show-toplevel) || exit 1
# Pattern 1: review a verified remote-tracking ref without checking out its branch.
# Refresh the intended ref separately if needed; use a unique unused path.
git worktree add --detach /tmp/review-pr-example origin/feature/payment-v2
# Inspect code first; only run it if trusted and authorized.
# Return outside the review tree before cleanup:
cd "$repo" || exit 1
git worktree remove /tmp/review-pr-example
# Pattern 2: detached checkout avoids main already checked out elsewhere.
git worktree add --detach /tmp/test-main-example main
# Prepare dependencies separately; use separate ports/databases for concurrent tests.
(cd /tmp/test-main-example && npm test) &
first=$!
(cd "$repo" && npm test) &
second=$!
wait "$first"; first_status=$?
wait "$second"; second_status=$?
printf 'Test exit statuses: %s %s\n' "$first_status" "$second_status"
# Inspect generated files before a separate cleanup step; never force-remove.
# Pattern 3: release branches must exist and not be checked out elsewhere.
git worktree add "$HOME/releases/v2.1" release/2.1
git worktree add "$HOME/releases/v2.0" release/2.0
patch_file="$HOME/patches/example-reviewed-fix.patch" # illustrative, not a CVE
# Review the patch and changed files in EACH tree; commit only intended paths.
git -C "$HOME/releases/v2.1" apply --check "$patch_file"
git -C "$HOME/releases/v2.1" apply "$patch_file"
git -C "$HOME/releases/v2.1" diff
# Repeat review/apply explicitly for v2.0; then stage specific files and commit.
# Pattern 4: separate CI script, run only with a verified CI_COMMIT_SHA.
# Generated/untracked files may make cleanup refuse; preserve and inspect them.
ci_worktree_build() (
repo=$(git rev-parse --show-toplevel) || exit 1
: "${CI_COMMIT_SHA:?Set a verified commit hash}"
build_dir=$(mktemp -d "${TMPDIR:-/tmp}/ci-worktree.XXXXXX") || exit 1
git worktree add --detach "$build_dir" "$CI_COMMIT_SHA" || exit 1
cleanup() {
cd "$repo" || return
git worktree remove "$build_dir" ||
printf 'Cleanup refused; inspect retained worktree: %s\n' "$build_dir" >&2
}
trap cleanup EXIT
cd "$build_dir" || exit 1
npm ci && npm run build && npm test
)
# Calling ci_worktree_build executes repository scripts; not called here.⚠️ כללים ומגבלות חשובים
בדרך כלל Git מונע ביצוע checkout של אותו ענף בשני עצי עבודה בו־זמנית. כך נמנעים עדכונים מתנגשים של אותו ענף. הודעת השגיאה הרגילה היא: fatal: 'feature/x' is already checked out מקור
כל עצי העבודה חולקים מסד אובייקטים אחד של .git. פעולות Git כמו fetch, log ו־blame יכולות לגשת להיסטוריה המשותפת, אך חלק מההפניות נפרדות לכל עץ. פקודות שבוחנות את קובצי העבודה או את האינדקס עשויות להחזיר תוצאות שונות. מקור
פתחו כל תיקייה כפרויקט נפרד בעורך. פרטי השילוב תלויים בעורך ובגרסה, ולכן יש לבדוק את התצורה שלכם. ב־VS Code, Remote - Containers הוא שם ישן של הרחבה; שם המוצר הנוכחי הוא Dev Containers. יש לבדוק את התנהגות הקונטיינר ועץ העבודה בתצורה שנבחרה. מקור
עצי עבודה אינם משכפלים את תיקיית האובייקטים של .git, אך כל עץ זקוק לקובצי העבודה שלו ועשויים להיות בו תלויות ותוצרי בנייה נפרדים. הנפח הנוסף תלוי במאגר ובכלים; דוגמת 500MB ו־100–200MB במקור לא הייתה תוצאת מדידה. מקור
עצי עבודה לעומת החלופות
⚖️ השוואה בין עצי עבודה לגישות אחרות
| גישה | החלפת הקשר | נפח אחסון | עבודה מקבילה | מתאים במיוחד ל־ |
|---|---|---|---|---|
| git worktree | ללא החלפת עותק העבודה הנוכחי | אובייקטים משותפים וקבצים נוספים | ✅ עבודה מקבילה אמיתית | משימות מקבילות באותו מאגר |
| git stash | ⚠️ מעבר מלא | ללא עותק עבודה שני | ❌ עבודה סדרתית בלבד | צורך קצר וזמני |
| שכפול שני | עותק עבודה נפרד | אחסון מאגר נפרד | ✅ עבודה מקבילה אמיתית | ניסויים מבודדים |
| commit זמני של עבודה ומעבר ענף | ⚠️ מעבר מלא | ללא עותק עבודה שני | ❌ עבודה סדרתית בלבד | כאשר stash אינו פתרון נקי |
כתיבת סקריפטים לעבודה יעילה עם עצי עבודה
# Bash-only educational helpers; runtime-untested.
# Review before adding to shell configuration. No settings changed by this article.
gwt-review() {
local branch="$1" repo dir
repo=$(git rev-parse --show-toplevel) || return
git check-ref-format --branch "$branch" >/dev/null || return
git fetch origin "refs/heads/$branch" || return
dir=$(mktemp -d "${TMPDIR:-/tmp}/review-worktree.XXXXXX") || return
git worktree add --detach "$dir" FETCH_HEAD || return
printf 'Reviewing at: %s\n' "$dir"
cd "$dir" || return
}
gwt-add() {
local branch="$1" repo repo_name short_branch dir
repo=$(git rev-parse --show-toplevel) || return
git check-ref-format --branch "$branch" >/dev/null || return
repo_name=$(basename "$repo")
short_branch=$(printf '%s' "$branch" | sed 's/[/:]/-/g')
dir="$(dirname "$repo")/${repo_name}-${short_branch}"
# main must exist; existing branch/path names intentionally cause refusal.
git worktree add -b "$branch" "$dir" main || return
printf 'Worktree at: %s\n' "$dir"
cd "$dir" || return
}
gwt-list() {
# Use Git's own path-safe human output rather than fragile awk parsing.
git worktree list
}
gwt-clean-reviews() {
# Inventory only. No bulk deletion from parsed text or global wildcard paths.
git worktree list
printf '%s\n' 'Inspect one exact review path, leave it, then use git worktree remove PATH.'
}עצי עבודה במאגרי monorepo ועם Node.js/npm
# Alternative package-manager examples, not consecutive steps.
# Dependencies and lifecycle scripts can execute code; trusted projects only.
# npm option: create the worktree once at an unused path.
git worktree add ../my-repo-feature feature/new-ui
(cd ../my-repo-feature && npm ci)
# pnpm ALTERNATIVE, after creating a suitable worktree once:
# (cd ../my-repo-feature && pnpm install --frozen-lockfile)
# Select the manager matching the repository lockfile and supported version.
# Caches/stores may reuse downloaded content, but install time is workload-specific.
# Each worktree can have separate node_modules and build outputs.
# In the repository's .gitignore, an in-tree rule may be appropriate:
# node_modules/
# Do NOT put ../*-worktree/ or sibling paths in this repository's .gitignore:
# ignore rules cannot match files outside the repository working tree.💡 שיטות עבודה ועצות שימושיות
../repo-hotfix, ../repo-review-123, ../repo-release-2.1. כך הפלט של gwt-list יהיה קריא.code /path/to/worktree, או השתמשו ב־״Open Directory״ של JetBrains כדי לפתוח סביבות פיתוח מקבילות לאותו בסיס קוד.~/projects/my-repo ← ~/projects/my-repo-hotfix. כך נמנעים מקינון עמוק ושומרים עבודה קשורה קרובה זו לזו.סיכום
עצי עבודה מאפשרים לכמה עותקי עבודה של מאגר אחד להתקיים יחד. הם יכולים לסייע בתיקונים דחופים, בסקירת בקשות משיכה, בבדיקות מקבילות ובתחזוקת גרסאות, תוך שיתוף אובייקטים והפרדת קובצי עבודה. הם אינם מבודדים כל משאב חיצוני: יציאות רשת, מסדי נתונים, מטמוני בנייה ופרטי גישה עדיין עשויים להיות משותפים. מקור
התחילו בקטן: בפעם הבאה שתצטרכו להחליף הקשר, נסו git worktree add במקום stash. כשההרגל מתבסס, עצי עבודה יכולים להפוך לחלק מרכזי בעבודה היומיומית שלכם עם Git.
כל דוגמאות המעטפת לא נבדקו בזמן ריצה ויש להתאימן במאגר בדיקה מורשה. יצירת עצי עבודה, commits ודחיפות משנה מצב; התקנת תלויות ובדיקות עלולות להריץ קוד מהמאגר. שום דוגמה לא הורצה. הסרה כפויה הוסרה מפני שהיא עלולה למחוק קבצים שלא נשמרו ב־commit. יש לנקות מתוך תיקייה שמחוץ לעץ היעד ולעצור אם Git מסרב; בדקו ושמרו קבצים במקום להוסיף --force. שמות הענפים, הגיבובים והטלאים הם להמחשה, לא הודעות אבטחה אמיתיות.