Spec-Zone.ru › Git

git-worktree

Имя

git-worktree — управление несколькими рабочими деревьями

Краткое описание

git worktree add [-f] [--detach] [--checkout] [--lock [--reason <string>]]
                 [--orphan] [(-b | -B) <new-branch>] <path> [<commit-ish>]
git worktree list [-v | --porcelain [-z]]
git worktree lock [--reason <string>] <worktree>
git worktree move <worktree> <new-path>
git worktree prune [-n] [-v] [--expire <expire>]
git worktree remove [-f] <worktree>
git worktree repair [<path>…​]
git worktree unlock <worktree>

Описание

Управление несколькими рабочими деревьями, связанными с одним репозиторием.

Репозиторий Git может поддерживать несколько рабочих деревьев, что позволяет одновременно извлечь более одной ветки. С помощью git worktree add с репозиторием связывается новое рабочее дерево, а также добавляются дополнительные метаданные, отличающие это рабочее дерево от других в том же репозитории. Рабочее дерево вместе с этими метаданными называется «рабочим деревом».

Это новое рабочее дерево называется «связанным рабочим деревом» в отличие от «основного рабочего дерева», подготовленного командами git-init[1] или git-clone[1]. У репозитория есть одно основное рабочее дерево (если это не bare-репозиторий) и ноль или более связанных рабочих деревьев. Когда связанное рабочее дерево больше не нужно, удалите его с помощью git worktree remove.

В простейшем случае git worktree add <path> автоматически создаёт новую ветку, имя которой совпадает с последним компонентом <path>; это удобно, если вы собираетесь работать над новой задачей. Например, git worktree add ../hotfix создаёт новую ветку hotfix и извлекает её в путь ../hotfix. Чтобы вместо этого работать с существующей веткой в новом рабочем дереве, используйте git worktree add <path> <branch>. Если же вы просто собираетесь внести некоторые экспериментальные изменения или провести тестирование, не затрагивая текущую разработку, часто удобно создать рабочее дерево throwaway, не связанное ни с одной веткой. Например, git worktree add -d <path> создаёт новое рабочее дерево с отделённым HEAD на том же коммите, что и текущая ветка.

Если рабочее дерево удалено без использования git worktree remove, связанные с ним административные файлы, расположенные в репозитории (см. раздел «ПОДРОБНОСТИ» ниже), в конечном итоге будут удалены автоматически (см. gc.worktreePruneExpire в git-config[1]). Также можно выполнить git worktree prune в основном или любом связанном рабочем дереве, чтобы удалить все устаревшие административные файлы.

Если рабочее дерево для связанного рабочего дерева находится на переносном устройстве или сетевом ресурсе, который не всегда подключён, можно предотвратить удаление его административных файлов, выполнив команду git worktree lock; при желании укажите --reason, чтобы объяснить, почему рабочее дерево заблокировано.

Команды

add <path> [<commit-ish>]

Создаёт рабочее дерево по пути <path> и извлекает в него <commit-ish>. Новое рабочее дерево связано с текущим репозиторием и использует общие данные, за исключением файлов, относящихся к отдельному рабочему дереву, таких как HEAD, index и т. д. Для удобства <commit-ish> может быть простым «-», что равнозначно @{-1}.

Если <commit-ish> — это имя ветки (обозначим её <branch>), и такая ветка не найдена, а параметры -b, -B и --detach не используются, но в единственном удалённом репозитории есть отслеживаемая ветка с таким же именем (обозначим её <remote>), команда действует так же, как:

$ git worktree add --track -b <branch> <path> <remote>/<branch>

Если ветка существует в нескольких удалённых репозиториях и один из них указан в переменной конфигурации checkout.defaultRemote, для устранения неоднозначности будет выбран именно он, даже если <branch> не является уникальным среди всех удалённых репозиториев. Например, задайте значение checkout.defaultRemote=origin, чтобы всегда извлекать удалённые ветки оттуда, если <branch> неоднозначно, но существует в удалённом репозитории origin. См. также checkout.defaultRemote в git-config[1].

Если <commit-ish> не указан и параметры -b, -B и --detach не используются, то для удобства новое рабочее дерево связывается с веткой (обозначим её <branch>), названной по результату $(basename <path>). Если <branch> не существует, автоматически создаётся новая ветка на основе HEAD, как если бы был указан параметр -b <branch>. Если <branch> существует, она будет извлечена в новое рабочее дерево, если только она не извлечена где-либо ещё; в противном случае команда откажется создавать рабочее дерево (если не используется --force).

Если <commit-ish> не указан, параметры --detach и --orphan не используются, а допустимых локальных веток (или удалённых веток, если задан --guess-remote) нет, то для удобства новое рабочее дерево связывается с новой ещё не созданной веткой с именем <branch> (по результату $(basename <path>), если не используются параметры -b или -B), как если бы команде был передан параметр --orphan. Если в репозитории настроен удалённый репозиторий и используется --guess-remote, но удалённых или локальных веток нет, команда завершится с предупреждением о том, что сначала следует получить данные из удалённого репозитория (или переопределить поведение с помощью -f/--force).

list

Выводит сведения о каждом рабочем дереве. Сначала выводится основное рабочее дерево, затем каждое из связанных рабочих деревьев. В выводе указывается, является ли рабочее дерево bare, какая ревизия извлечена в данный момент, какая ветка извлечена (или «отделённый HEAD», если ветки нет), а также пометки «заблокировано», если рабочее дерево заблокировано, и «можно очистить», если команда prune может удалить сведения о нём.

lock

Если рабочее дерево находится на переносном устройстве или сетевом ресурсе, который не всегда подключён, заблокируйте его, чтобы предотвратить автоматическое удаление административных файлов. Это также предотвращает перемещение или удаление рабочего дерева. При желании укажите причину блокировки с помощью --reason.

move

Перемещает рабочее дерево в новое расположение. Обратите внимание, что основное рабочее дерево и связанные рабочие деревья, содержащие подмодули, нельзя переместить с помощью этой команды. Однако команда git worktree repair может восстановить связь со связанными рабочими деревьями, если переместить основное рабочее дерево вручную.

prune

Удаляет из $GIT_DIR/worktrees сведения о рабочих деревьях, рабочие каталоги которых отсутствуют. Полезно после ручного удаления рабочего дерева, которое больше не требуется (но в следующий раз используйте для этого «git worktree remove»). Кроме того, если вы moved рабочее дерево в другое место, из-за чего сведения о нём стали устаревшими, см. «git worktree repair», чтобы восстановить связь с новым расположением рабочего дерева.

remove

Удаляет рабочее дерево. Можно удалить только чистые рабочие деревья (без неотслеживаемых файлов и изменений в отслеживаемых файлах). Грязные рабочие деревья и рабочие деревья с подмодулями можно удалить с помощью --force. Основное рабочее дерево удалить нельзя.

repair [<path>...]

По возможности восстанавливает административные файлы рабочего дерева, если они были повреждены или устарели из-за внешних факторов.

Например, если основное рабочее дерево (или bare-репозиторий) перемещено, связанные рабочие деревья не смогут его найти. Выполнение команды repair в основном рабочем дереве восстановит связь связанных рабочих деревьев с основным.

Аналогично, если рабочее дерево для связанного рабочего дерева перемещено без использования git worktree move, основное рабочее дерево (или bare-репозиторий) не сможет его найти. Выполнение команды repair в недавно перемещённом рабочем дереве восстановит связь. Если перемещено несколько связанных рабочих деревьев, выполните repair из любого рабочего дерева, указав новые <path> каждого дерева в качестве аргументов, чтобы восстановить связь со всеми указанными путями.

Если основное и связанные рабочие деревья были перемещены или скопированы вручную, выполните repair в основном рабочем дереве и укажите новые <path> каждого связанного рабочего дерева, чтобы восстановить все связи в обоих направлениях.

unlock

Разблокирует рабочее дерево, разрешая его очистку, перемещение или удаление.

Параметры

-f
--force

По умолчанию add отказывается создавать новое рабочее дерево, если <commit-ish> — это имя ветки, уже извлечённой в другом рабочем дереве, или если <path> уже назначен какому-либо рабочему дереву, но отсутствует (например, если <path> был удалён вручную). Этот параметр отключает эти меры защиты. Чтобы добавить отсутствующий, но заблокированный путь рабочего дерева, укажите --force дважды.

move отказывается перемещать заблокированное рабочее дерево, если параметр --force не указан дважды. Если целевой путь уже назначен другому рабочему дереву, но оно отсутствует (например, если <new-path> был удалён вручную), --force позволяет выполнить перемещение; если целевой путь заблокирован, укажите --force дважды.

remove отказывается удалять грязное рабочее дерево, если не указан параметр --force. Чтобы удалить заблокированное рабочее дерево, укажите --force дважды.

-b <new-branch>
-B <new-branch>

С параметром add создаёт новую ветку с именем <new-branch>, начинающуюся с <commit-ish>, и извлекает <new-branch> в новое рабочее дерево. Если <commit-ish> не указан, по умолчанию используется HEAD. По умолчанию -b отказывается создавать новую ветку, если она уже существует. -B отключает эту защиту, сбрасывая <new-branch> к <commit-ish>.

-d
--detach

С параметром add отделяет HEAD в новом рабочем дереве. См. раздел «ОТДЕЛЁННЫЙ HEAD» в git-checkout[1].

--checkout
--no-checkout

По умолчанию add извлекает <commit-ish>, однако параметр --no-checkout можно использовать, чтобы пропустить извлечение и выполнить настройку, например настроить разреженное извлечение. См. раздел «Разреженное извлечение» в git-read-tree[1].

--guess-remote
--no-guess-remote

При использовании worktree add <path> без <commit-ish>, если в единственном удалённом репозитории есть отслеживаемая ветка, имя которой совпадает с последним компонентом <path>, новая ветка будет создана не на основе HEAD, а на основе этой удалённой отслеживаемой ветки; она будет указана как вышестоящая для новой ветки.

Это поведение также можно сделать используемым по умолчанию с помощью параметра конфигурации worktree.guessRemote.

--relative-paths
--no-relative-paths

Связывает рабочие деревья с помощью относительных или абсолютных путей (по умолчанию). Переопределяет параметр конфигурации worktree.useRelativePaths; см. git-config[1].

С параметром repair файлы связей будут обновлены при несоответствии абсолютных и относительных путей, даже если связи корректны.

--track
--no-track

При создании новой ветки, если <commit-ish> является веткой, она указывается как вышестоящая для новой ветки. Это поведение используется по умолчанию, если <commit-ish> является удалённой отслеживаемой веткой. Подробнее см. --track в git-branch[1].

--lock

Оставляет рабочее дерево заблокированным после создания. Это равнозначно выполнению git worktree lock после git worktree add, но без гонки.

-n
--dry-run

С параметром prune ничего не удаляет, а только сообщает, что было бы удалено.

--orphan

С параметром add создаёт новое рабочее дерево и пустой индекс, связывая рабочее дерево с новой ещё не созданной веткой с именем <new-branch>.

--porcelain

С параметром list выводит данные в формате, удобном для разбора сценариями. Этот формат остаётся стабильным в разных версиях Git и независимо от пользовательской конфигурации. Рекомендуется использовать этот параметр вместе с -z. Подробнее см. ниже.

-z

Завершает каждую строку символом NUL, а не переводом строки, когда --porcelain указан вместе с list. Это позволяет разбирать вывод, если путь рабочего дерева содержит символ перевода строки.

-q
--quiet

С параметром add подавляет информационные сообщения.

-v
--verbose

С параметром prune сообщает обо всех удалениях.

С параметром list выводит дополнительные сведения о рабочих деревьях (см. ниже).

--expire <time>

С параметром prune удаляет только отсутствующие рабочие деревья, если они старше <time>.

С параметром list помечает отсутствующие рабочие деревья как подлежащие очистке, если они старше <time>.

--reason <string>

С параметром lock или вместе с add --lock указывает причину блокировки рабочего дерева.

<worktree>

Рабочие деревья можно указать по относительному или абсолютному пути.

Если последние компоненты пути рабочего дерева уникальны среди всех рабочих деревьев, их можно использовать для его указания. Например, если у вас есть только два рабочих дерева — /abc/def/ghi и /abc/def/ggg, — то для указания первого достаточно ghi или def/ghi.

Ссылки

При использовании нескольких рабочих деревьев некоторые ссылки являются общими для всех рабочих деревьев, а другие относятся к отдельному рабочему дереву. Например, HEAD отличается для каждого рабочего дерева. В этом разделе описаны правила совместного использования и способы доступа к ссылкам одного рабочего дерева из другого.

В целом все псевдоссылки относятся к отдельному рабочему дереву, а все ссылки, начинающиеся с refs/, являются общими. Псевдоссылки — это такие ссылки, как HEAD, расположенные непосредственно в $GIT_DIR, а не внутри $GIT_DIR/refs. Однако есть исключения: ссылки внутри refs/bisect, refs/worktree и refs/rewritten не являются общими.

К ссылкам, относящимся к отдельному рабочему дереву, всё же можно получить доступ из другого рабочего дерева через два специальных пути: main-worktree и worktrees. Первый предоставляет доступ к ссылкам основного рабочего дерева, относящимся к отдельному рабочему дереву, а второй — к таким ссылкам всех связанных рабочих деревьев.

Например, main-worktree/HEAD или main-worktree/refs/bisect/good разрешаются в те же значения, что и HEAD и refs/bisect/good основного рабочего дерева соответственно. Аналогично, worktrees/foo/HEAD или worktrees/bar/refs/bisect/bad эквивалентны $GIT_COMMON_DIR/worktrees/foo/HEAD и $GIT_COMMON_DIR/worktrees/bar/refs/bisect/bad.

Для доступа к ссылкам лучше не просматривать содержимое $GIT_DIR напрямую. Вместо этого используйте такие команды, как git-rev-parse[1] или git-update-ref[1], которые корректно обрабатывают ссылки.

Файл конфигурации

По умолчанию файл config репозитория является общим для всех рабочих деревьев. Если в общем файле конфигурации заданы переменные core.bare или core.worktree, а extensions.worktreeConfig отключён, они будут применяться только к основному рабочему дереву.

Чтобы использовать конфигурацию, специфичную для рабочего дерева, можно включить расширение worktreeConfig, например:

$ git config extensions.worktreeConfig true

В этом режиме специальная конфигурация хранится по пути, указанному в git rev-parse --git-path config.worktree. Добавить или обновить конфигурацию в этом файле можно с помощью git config --worktree. Старые версии Git откажутся работать с репозиториями, в которых включено это расширение.

Обратите внимание, что в этом файле исключение для core.bare и core.worktree отсутствует. Если они есть в $GIT_DIR/config, их необходимо переместить в config.worktree основного рабочего дерева. Заодно можно проверить и переместить другие параметры конфигурации, которые не следует делать общими для всех рабочих деревьев:

  • core.worktree никогда не следует делать общим.

  • core.bare не следует делать общим, если его значение — core.bare=true.

  • core.sparseCheckout не следует делать общим, если только вы не уверены, что во всех рабочих деревьях всегда используется разреженное извлечение.

Подробнее см. документацию по extensions.worktreeConfig в git-config[1].

Подробности

Каждое связанное рабочее дерево имеет собственный подкаталог в каталоге репозитория $GIT_DIR/worktrees. Имя подкаталога обычно совпадает с базовым именем пути связанного рабочего дерева, к которому при необходимости добавляется номер для обеспечения уникальности. Например, когда $GIT_DIR=/path/main/.git команда git worktree add /path/other/test-next next создаёт связанное рабочее дерево в /path/other/test-next, она также создаёт каталог $GIT_DIR/worktrees/test-next (или $GIT_DIR/worktrees/test-next1, если test-next уже занято).

В связанном рабочем дереве $GIT_DIR указывает на этот собственный каталог (например, /path/main/.git/worktrees/test-next в приведённом примере), а $GIT_COMMON_DIR указывает на $GIT_DIR основного рабочего дерева (например, /path/main/.git). Эти параметры задаются в файле .git, расположенном в корневом каталоге связанного рабочего дерева.

При разрешении путей с помощью git rev-parse --git-path используется либо $GIT_DIR, либо $GIT_COMMON_DIR в зависимости от пути. Например, в связанном рабочем дереве git rev-parse --git-path HEAD возвращает /path/main/.git/worktrees/test-next/HEAD (а не /path/other/test-next/.git/HEAD или /path/main/.git/HEAD), тогда как git rev-parse --git-path refs/heads/master использует $GIT_COMMON_DIR и возвращает /path/main/.git/refs/heads/master, поскольку ссылки общие для всех рабочих деревьев, за исключением refs/bisect, refs/worktree и refs/rewritten.

Дополнительную информацию см. в gitrepository-layout[5]. Как правило, не следует предполагать, относится ли путь к $GIT_DIR или $GIT_COMMON_DIR, если нужно напрямую получить доступ к чему-либо внутри $GIT_DIR. Используйте git rev-parse --git-path, чтобы получить конечный путь.

Если вы вручную переместили связанное рабочее дерево, необходимо обновить файл gitdir в каталоге этой записи. Например, если связанное рабочее дерево перемещено в /newpath/test-next, а его файл .git указывает на /path/main/.git/worktrees/test-next, обновите /path/main/.git/worktrees/test-next/gitdir, чтобы он указывал на /newpath/test-next. Ещё лучше запустить git worktree repair, чтобы автоматически восстановить связь.

Чтобы предотвратить удаление записи $GIT_DIR/worktrees (это может быть полезно в некоторых ситуациях, например, когда рабочее дерево записи хранится на переносном устройстве), используйте команду git worktree lock, которая добавляет в каталог записи файл с именем locked. В этом файле обычным текстом указана причина. Например, если файл .git связанного рабочего дерева указывает на /path/main/.git/worktrees/test-next, файл с именем /path/main/.git/worktrees/test-next/locked предотвратит удаление записи test-next. Подробнее см. в gitrepository-layout[5].

Если включён параметр extensions.worktreeConfig, файл конфигурации .git/worktrees/<id>/config.worktree считывается после .git/config.

Формат вывода списка

Команда worktree list поддерживает два формата вывода. В формате по умолчанию сведения отображаются в столбцах одной строки. Например:

$ git worktree list
/path/to/bare-source            (bare)
/path/to/linked-worktree        abcd1234 [master]
/path/to/other-linked-worktree  1234abc  (detached HEAD)

Команда также отображает аннотации для каждого рабочего дерева в соответствии с его состоянием. Возможны следующие аннотации:

  • locked, если рабочее дерево заблокировано.

  • prunable, если рабочее дерево можно удалить с помощью команды git worktree prune.

$ git worktree list
/path/to/linked-worktree    abcd1234 [master]
/path/to/locked-worktree    acbd5678 (brancha) locked
/path/to/prunable-worktree  5678abc  (detached HEAD) prunable

Для этих аннотаций также может быть указана причина, которую можно увидеть в подробном режиме. В этом случае аннотация переносится на следующую строку с отступом, за ней следует дополнительная информация.

$ git worktree list --verbose
/path/to/linked-worktree              abcd1234 [master]
/path/to/locked-worktree-no-reason    abcd5678 (detached HEAD) locked
/path/to/locked-worktree-with-reason  1234abcd (brancha)
        locked: worktree path is mounted on a portable device
/path/to/prunable-worktree            5678abc1 (detached HEAD)
        prunable: gitdir file points to non-existent location

Обратите внимание: если дополнительная информация доступна, аннотация переносится на следующую строку; в противном случае она остаётся в той же строке, что и само рабочее дерево.

Формат Porcelain

В формате Porcelain для каждого атрибута выводится отдельная строка. Если указан параметр -z, строки завершаются нулевым байтом, а не символом новой строки. Атрибуты перечисляются в виде метки и значения, разделённых одним пробелом. Логические атрибуты (например, bare и detached) выводятся только в виде метки и присутствуют, только если их значение равно true. Некоторые атрибуты (например, locked) могут выводиться только в виде метки или вместе со значением, в зависимости от наличия причины. Первым атрибутом рабочего дерева всегда является worktree; пустая строка обозначает конец записи. Например:

$ git worktree list --porcelain
worktree /path/to/bare-source
bare

worktree /path/to/linked-worktree
HEAD abcd1234abcd1234abcd1234abcd1234abcd1234
branch refs/heads/master

worktree /path/to/other-linked-worktree
HEAD 1234abc1234abc1234abc1234abc1234abc1234a
detached

worktree /path/to/linked-worktree-locked-no-reason
HEAD 5678abc5678abc5678abc5678abc5678abc5678c
branch refs/heads/locked-no-reason
locked

worktree /path/to/linked-worktree-locked-with-reason
HEAD 3456def3456def3456def3456def3456def3456b
branch refs/heads/locked-with-reason
locked reason why is locked

worktree /path/to/linked-worktree-prunable
HEAD 1233def1234def1234def1234def1234def1234b
detached
prunable gitdir file points to non-existent location

Если не используется параметр -z, любые «нестандартные» символы в причине блокировки, например символы новой строки, экранируются, а вся причина заключается в кавычки, как описано для переменной конфигурации core.quotePath (см. git-config[1]). Например:

$ git worktree list --porcelain
...
locked "reason\nwhy is locked"
...

Примеры

Вы находитесь в разгаре рефакторинга, когда заходит начальник и требует немедленно что-нибудь исправить. Обычно в такой ситуации можно воспользоваться командой git-stash[1], чтобы временно сохранить изменения, однако ваше рабочее дерево настолько захламлено (в нём есть новые, перемещённые и удалённые файлы и множество других разрозненных изменений), что вы не хотите рисковать и трогать что-либо в нём. Вместо этого вы создаёте временное связанное рабочее дерево, чтобы внести срочное исправление, удаляете его после завершения и затем возвращаетесь к прежнему сеансу рефакторинга.

$ git worktree add -b emergency-fix ../temp master
$ pushd ../temp
# ... hack hack hack ...
$ git commit -a -m 'emergency fix for boss'
$ popd
$ git worktree remove ../temp

Конфигурация

Всё содержимое этого раздела ниже данной строки выборочно включено из документации git-config[1]. Здесь приведено то же содержимое, что и в ней:

worktree.guessRemote

Если ветка не указана и не используется ни -b, ни -B, ни --detach, то git worktree add по умолчанию создаёт новую ветку от HEAD. Если параметру worktree.guessRemote присвоено значение true, команда worktree add пытается найти ветку удалённого отслеживания, имя которой однозначно совпадает с именем новой ветки. Если такая ветка существует, она переключается, а новая ветка настраивается как её «вышестоящая». Если найти такое совпадение не удаётся, создаётся новая ветка от текущего HEAD.

worktree.useRelativePaths

Связывать рабочие деревья с помощью относительных путей (если задано значение «true») или абсолютных путей (если задано значение «false»). Это особенно полезно в конфигурациях, где репозиторий и рабочие деревья могут перемещаться между разными расположениями или средами. По умолчанию используется значение «false».

Обратите внимание: установка для worktree.useRelativePaths значения «true» подразумевает включение параметра конфигурации extensions.relativeWorktrees (см. git-config[1]), что делает этот параметр несовместимым со старыми версиями Git.

Ошибки

Возможность одновременно извлекать несколько рабочих деревьев в целом всё ещё является экспериментальной, а поддержка подмодулей реализована не полностью. НЕ рекомендуется создавать несколько рабочих деревьев для суперпроекта.

worktree

© 2005–2026 Linus Torvalds and others
Licensed under the GNU General Public License version 2.
https://git-scm.com/docs/git-worktree

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API