简体   繁体   English

Git 的多个工作目录?

[英]Multiple working directories with Git?

I'm not sure if this is something supported by Git, but in theory it seems like it should work to me.我不确定这是否受 Git 支持,但理论上它似乎对我有用。

My workflow often involves my editing of files in multiple branches simultaneously.我的工作流程经常涉及我同时在多个分支中编辑文件。 In other words, I often want to open a few files in one branch is while I edit the contents of another file in another branch.换句话说,我经常想在一个分支中打开几个文件,而我在另一个分支中编辑另一个文件的内容。

My typical solution to this is to make two checkouts, but it's a shame I can't share branches and refs between them.我对此的典型解决方案是进行两次结帐,但很遗憾我不能在它们之间共享分支和引用。 What I would like is to just have two working directories managed by the same.git folder.我想要的是只有两个工作目录由相同的.git 文件夹管理。

I'm aware of local git clone solutions (the default, which is to hardlink shared objects, and the --shared option, which sets up an alternate object store with the original repo), but these solutions only cut down on disk space usage, and especially in the case of --shared, seem fraught with peril.我知道本地 git 克隆解决方案(默认设置是硬链接共享对象,以及 --shared 选项,它使用原始存储库设置备用 object 存储),但这些解决方案只会减少磁盘空间使用,尤其是在 --shared 的情况下,似乎充满了危险。

Is there a way to use one.git folder, and have two working directories backed by it?有没有办法使用一个.git 文件夹,并有两个工作目录支持它? Or is Git hardcoded to have just one working directory checked out at any time?还是 Git 被硬编码为在任何时候只检出一个工作目录?

Git 2.5 proposes since July 2015 a replacement for contrib/workdir/git-new-workdir : git worktree Git 2.5 提议自 2015 年 7 月起替换contrib/workdir/git-new-workdirgit 工作树

See commit 68a2e6a by Junio C Hamano ( gitster ) .请参阅Junio C Hamano ( gitster )提交 68a2e6a

The release note mentions : 发行说明提到

A replacement for contrib/workdir/git-new-workdir that does not rely on symbolic links and make sharing of objects and refs safer by making the borrowee and borrowers aware of each other. contrib/workdir/git-new-workdir的替代品,它不依赖于符号链接,并通过让借用者和借用者相互了解来使对象和引用的共享更安全。

See commit 799767cc9 (Git 2.5rc2)请参阅提交 799767cc9 (Git 2.5rc2)

That means you now can do a git worktree add <path> [<branch>]这意味着您现在可以执行git worktree add <path> [<branch>]

Create <path> and checkout <branch> into it.创建<path>并将<branch>签入其中。 The new working directory is linked to the current repository, sharing everything except working directory specific files such as HEAD, index, etc. The git worktree section adds:新的工作目录链接到当前存储库,共享除工作目录特定文件(如 HEAD、索引等)之外的git worktree部分添加:

A git repository can support multiple working trees , allowing you to check out more than one branch at a time. git 存储库可以支持多个工作树,允许您一次检查多个分支。
With git worktree add , a new working tree is associated with the repository.使用git worktree add ,新的工作树与存储库相关联。

This new working tree is called a "linked working tree" as opposed to the "main working tree" prepared by " git init " or " git clone " .这个新的工作树被称为“链接工作树”,而不是由“ git init ”或“ git clone ”准备的“主工作树”
A repository has one main working tree (if it's not a bare repository) and zero or more linked working trees.一个存储库有一个主要的工作树(如果它不是一个裸存储库)和零个或多个链接的工作树。

details:细节:

Each linked working tree has a private sub-directory in the repository's $GIT_DIR/worktrees directory.每个链接的工作树在存储库的$GIT_DIR/worktrees目录中都有一个私有子目录。
The private sub-directory's name is usually the base name of the linked working tree's path, possibly appended with a number to make it unique.私有子目录的名称通常是链接工作树路径的基本名称,可能会附加一个数字以使其唯一。
For example, when $GIT_DIR=/path/main/.git the command git worktree add /path/other/test-next next creates:例如,当$GIT_DIR=/path/main/.git命令git worktree add /path/other/test-next next创建:

  • the linked working tree in /path/other/test-next and /path/other/test-next中的链接工作树和
  • also creates a $GIT_DIR/worktrees/test-next directory (or $GIT_DIR/worktrees/test-next1 if test-next is already taken).还创建一个$GIT_DIR/worktrees/test-next目录(或$GIT_DIR/worktrees/test-next1如果test-next已经被采用)。

Within a linked working tree:在链接的工作树中:

  • $GIT_DIR is set to point to this private directory (eg /path/main/.git/worktrees/test-next in the example) and $GIT_DIR设置为指向这个私有目录(例如/path/main/.git/worktrees/test-next在示例中)和
  • $GIT_COMMON_DIR is set to point back to the main working tree's $GIT_DIR (eg /path/main/.git ). $GIT_COMMON_DIR设置为指向主工作树的$GIT_DIR (例如/path/main/.git )。

These settings are made in a .git file located at the top directory of the linked working tree.这些设置在位于链接工作树顶部目录的.git文件中进行。

When you are done with a linked working tree you can simply delete it.完成链接工作树后,您只需将其删除即可。
The working tree's administrative files in the repository will eventually be removed automatically (see gc.pruneworktreesexpire in git config ), or you can run git worktree prune in the main or any linked working tree to clean up any stale administrative files.存储库中工作树的管理文件最终将被自动删除(请参阅gc.pruneworktreesexpire配置中的git config ),或者您可以在主或任何链接的工作树中运行git worktree prune以清理任何陈旧的管理文件。


Warning: there is still a git worktree "BUGS" section to be aware of.警告:还有一个git worktree “BUGS”部分需要注意。

The support for submodules is incomplete . 对子模块的支持不完整
It is NOT recommended to make multiple checkouts of a superproject.不建议对一个超级项目进行多次检查。


Note: with git 2.7rc1 (Nov 2015) you are able to list your worktrees.注意:使用 git 2.7rc1(2015 年 11 月),您可以列出您的工作树。
See commit bb9c03b , commit 92718b7 , commit 5193490 , commit 1ceb7f9 , commit 1ceb7f9 , commit 5193490 , commit 1ceb7f9 , commit 1ceb7f9 (08 Oct 2015), commit 92718b7 , commit 5193490 , commit 1ceb7f9 , commit 1ceb7f9 (08 Oct 2015), commit 5193490 , commit 1ceb7f9 (08 Oct 2015), commit 1ceb7f9 (08 Oct 2015), and commit ac6c561 (02 Oct 2015) by Michael Rappazzo ( rappazzo ) .参见提交BB9C03B提交92718B7提交5193490提交1CEB7F9提交1CEB7F9提交5193490提交1CEB7F9提交1CEB7F9 (2015年10月8日), 提案92718B7提交5193490,1CE 1CEB7901CECTB79.SCEB79B79 (08) 1CE 1CEB7F9提交 1ceb7f9 (2015 年 10 月 8 日)、 提交 1ceb7f9 (2015 年 10 月 8 日)和提交 ac6c561 (2015 年 10 月 2 日),作者为Michael Rappazzo ( rappazzo )
(Merged by Junio C Hamano -- gitster -- in commit a46dcfb , 26 Oct 2015) (由Junio C Hamano -- gitster --提交 a46dcfb中合并,2015 年 10 月 26 日)

worktree : add ' list ' command worktree :添加“ list ”命令

' git worktree list ' iterates through the worktree list, and outputs details of the worktree including the path to the worktree, the currently checked out revision and branch, and if the work tree is bare. ' git worktree list ' 遍历工作树列表,并输出工作树的详细信息,包括工作树的路径、当前签出的修订和分支,以及工作树是否是裸露的。

$ git worktree list /path/to/bare-source (bare) /path/to/linked-worktree abcd1234 [master] /path/to/other-linked-worktree 1234abc (detached HEAD) $ git 工作树列表 /path/to/bare-source (bare) /path/to/linked-worktree abcd1234 [master] /path/to/other-linked-worktree 1234abc (分离 HEAD)

There is also porcelain format option available.还有瓷器格式选项可用。

The porcelain format has a line per attribute.瓷器格式的每个属性都有一行。

  • Attributes are listed with a label and value separated by a single space.属性以 label 和由单个空格分隔的值列出。
  • Boolean attributes (like 'bare' and 'detached') are listed as a label only, and are only present if and only if the value is true. Boolean 属性(如“裸”和“分离”)仅作为 label 列出,并且仅当且仅当值为 true 时才存在。
  • An empty line indicates the end of a worktree空行表示工作树的结束

For instance:例如:

$ 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

Note: if you MOVE a worktree folder, you need to manually update the gitdir file.注意:如果移动工作树文件夹,则需要手动更新gitdir文件。

See commit 618244e (22 Jan 2016), and commit d4cddd6 (18 Jan 2016) by Nguyễn Thái Ngọc Duy ( pclouds ) .请参阅Nguyễn Thai Ngọc Duy ( pclouds )的提交618244e (2016 年 1 月 22 日)和提交 d4cddd6 (2016 年 1 月 18 日)。
Helped-by: Eric Sunshine ( sunshineco ) .帮助者: Eric Sunshine ( sunshineco )
(Merged by Junio C Hamano -- gitster -- in commit d0a1cbc , 10 Feb 2016) (由Junio C Hamano -- gitster --提交 d0a1cbc中合并,2016 年 2 月 10 日)

The new doc in git 2.8 (March 2016) will include: git 2.8(2016 年 3 月)中的新文档将包括:

If you move a linked working tree, you need to update the ' gitdir ' file in the entry's directory.如果移动链接的工作树,则需要更新条目目录中的 ' gitdir ' 文件。
For example, if a linked working tree is moved to /newpath/test-next and its .git file points to /path/main/.git/worktrees/test-next , then update /path/main/.git/worktrees/test-next/gitdir to reference /newpath/test-next instead.例如,如果链接的工作树移动到/newpath/test-next并且其.git文件指向/path/main/.git/worktrees/test-next ,则更新/path/main/.git/worktrees/test-next/gitdir改为引用/newpath/test-next


Be careful when deleting a branch: before git 2.9 (June 2016), you could delete one in use in another working tree.删除分支时要小心:在 git 2.9(2016 年 6 月)之前,您可以删除另一个工作树中正在使用的分支。

When " git worktree " feature is in use, " git branch -d " allowed deletion of a branch that is checked out in another worktree.当使用“ git worktree ”功能时,“ git branch -d ”允许删除在另一个工作树中签出的分支。

See commit f292244 (29 Mar 2016) by Kazuki Yamaguchi ( rhenium ) .请参阅Kazuki Yamaguchi rhenium rhenium ) 的提交 f292244 (2016 年 3 月 29 日)。
Helped-by: Eric Sunshine ( sunshineco ) .帮助者: Eric Sunshine ( sunshineco )
(Merged by Junio C Hamano -- gitster -- in commit 4fca4e3 , 13 Apr 2016) (由Junio C Hamano -- gitster --提交 4fca4e3中合并,2016 年 4 月 13 日)

branch -d : refuse deleting a branch which is currently checked out branch -d :拒绝删除当前已签出的分支

When a branch is checked out by current working tree, deleting the branch is forbidden.当当前工作树检出一个分支时,禁止删除该分支。
However when the branch is checked out only by other working trees, deleting incorrectly succeeds.但是,当分支仅由其他工作树签出时,删除错误会成功。
Use find_shared_symref() to check if the branch is in use, not just comparing with the current working tree's HEAD.使用find_shared_symref()检查分支是否正在使用,而不仅仅是与当前工作树的 HEAD 进行比较。


Similarly, before git 2.9 (June 2016), renaming a branch checked out in another worktree did not adjust the symbolic HEAD in said other worktree.同样,在 git 2.9(2016 年 6 月)之前,重命名在另一个工作树中签出的分支不会调整所述另一个工作树中的符号 HEAD。

See commit 18eb3a9 (08 Apr 2016), and commit 70999e9 , commit 2233066 (27 Mar 2016) by Kazuki Yamaguchi ( rhenium ) .请参阅Kazuki Yamaguchi rhenium rhenium ) 的提交18eb3a9 (2016 年 4 月 8 日)和提交 70999e9提交 2233066 (2016 年 3 月 27 日)。
(Merged by Junio C Hamano -- gitster -- in commit 741a694 , 18 Apr 2016) (由Junio C Hamano -- gitster --提交 741a694中合并,2016 年 4 月 18 日)

branch -m : update all per-worktree HEADs branch -m :更新所有每个工作树的 HEAD

When renaming a branch, currently only the HEAD of current working tree is updated, but it must update HEADs of all working trees which point at the old branch.重命名分支时,当前只更新当前工作树的 HEAD,但必须更新所有指向旧分支的工作树的 HEAD。

This is the current behavior, /path/to/wt's HEAD is not updated:这是当前的行为,/path/to/wt 的 HEAD 没有更新:

 % git worktree list /path/to 2c3c5f2 [master] /path/to/wt 2c3c5f2 [oldname] % git branch -m master master2 % git worktree list /path/to 2c3c5f2 [master2] /path/to/wt 2c3c5f2 [oldname] % git branch -m oldname newname % git worktree list /path/to 2c3c5f2 [master2] /path/to/wt 0000000 [oldname]

This patch fixes this issue by updating all relevant worktree HEADs when renaming a branch.此补丁通过在重命名分支时更新所有相关的工作树 HEAD 来解决此问题。


The locking mechanism is officially supported with git 2.10 (Q3 2016) git 2.10 (Q3 2016) 正式支持锁定机制

See commit 080739b , commit 6d30862 , commit 58142c0 , commit 346ef53 , commit 346ef53 , commit 58142c0 , commit 346ef53 , commit 346ef53 (13 Jun 2016), and commit 984ad9e , commit 6835314 (03 Jun 2016) by Nguyễn Thái Ngọc Duy ( pclouds ) . See commit 080739b , commit 6d30862 , commit 58142c0 , commit 346ef53 , commit 346ef53 , commit 58142c0 , commit 346ef53 , commit 346ef53 (13 Jun 2016), and commit 984ad9e , commit 6835314 (03 Jun 2016) by Nguyễn Thái Ngọc Duy ( pclouds ) .
Suggested-by: Eric Sunshine ( sunshineco ) .推荐人: Eric Sunshine ( sunshineco )
(Merged by Junio C Hamano -- gitster -- in commit 2c608e0 , 28 Jul 2016) (由Junio C Hamano -- gitster --提交 2c608e0中合并,2016 年 7 月 28 日)

git worktree lock [--reason <string>] <worktree>
git worktree unlock <worktree>

If a linked working tree is stored on a portable device or network share which is not always mounted, you can prevent its administrative files from being pruned by issuing the git worktree lock command, optionally specifying --reason to explain why the working tree is locked.如果链接的工作树存储在不总是挂载的便携式设备或网络共享上,您可以通过发出git worktree lock命令来防止其管理文件被修剪,可选择指定--reason来解释工作树被锁定的原因.

<worktree> : If the last path components in the working tree's path is unique among working trees, it can be used to identify worktrees. <worktree> :如果工作树路径中的最后一个路径组件在工作树中是唯一的,则可以用来识别工作树。
For example if you only have to working trees at " /abc/def/ghi " and " /abc/def/ggg ", then " ghi " or " def/ghi " is enough to point to the former working tree.例如,如果您只需要在“ /abc/def/ghi ”和“ /abc/def/ggg ”处工作树,那么“ ghi ”或“ def/ghi ”就足以指向前一个工作树。


Git 2.13 (Q2 2017) add a lock option in commit 507e6e9 (12 Apr 2017) by Nguyễn Thái Ngọc Duy ( pclouds ) . Git 2.13(2017 年第二季度)在Nguyễn Thái Ngọc Duy ( pclouds )提交 507e6e9 (2017 年 4 月 12 日)中添加lock选项
Suggested-by: David Taylor ( dt ) .推荐人:大卫·泰勒 ( dt )
Helped-by: Jeff King ( peff ) .帮助者: Jeff King ( peff )
(Merged by Junio C Hamano -- gitster -- in commit e311597 , 26 Apr 2017) (由Junio C Hamano -- gitster --提交 e311597中合并,2017 年 4 月 26 日)

Allow to lock a worktree immediately after it's created.允许在创建工作树后立即锁定它。
This helps prevent a race between " git worktree add; git worktree lock " and " git worktree prune ".这有助于防止“ git worktree add; git worktree lock ”和“ git worktree prune ”之间的竞争。

So git worktree add' --lock is the equivalent of git worktree lock after git worktree add , but without race condition.所以git worktree add' --lock相当于 git git worktree add之后的 git git worktree lock ,但没有竞争条件。


Git 2.17+ (Q2 2018) adds git worktree move / git worktree remove : see this answer . Git 2.17+(2018 年第二季度)添加git worktree move / git worktree remove请参阅此答案


Git 2.19 (Q3 2018) add a " --quiet " option to make " git worktree add " less verbose. Git 2.19(2018 年第三季度)添加“ --quiet ”选项以使“ git worktree add ”不那么冗长。

See commit 371979c (15 Aug 2018) by Elia Pinto ( devzero2000 ) .请参阅Elia Pinto ( devzero2000 )提交 371979c (2018 年 8 月 15 日)。
Helped-by: Martin Ågren martin.agren@gmail.com, Duy Nguyen ( pclouds ) , and Eric Sunshine ( sunshineco ) .帮助者:Martin Ågren martin.agren@gmail.com、 Duy Nguyen ( pclouds )Eric Sunshine ( sunshineco )
(Merged by Junio C Hamano -- gitster -- in commit a988ce9 , 27 Aug 2018) (由Junio C Hamano -- gitster --提交 a988ce9中合并,2018 年 8 月 27 日)

worktree : add --quiet option worktree :添加--quiet选项

Add the ' --quiet ' option to git worktree , as for the other git commands.与其他git命令一样,将“ --quiet ”选项添加到git worktree
' add ' is the only command affected by it since all other commands, except ' list ', are currently silent by default. ' add ' 是唯一受它影响的命令,因为除了 ' list ' 之外的所有其他命令当前默认是静默的。


Note that " git worktree add " used to do a "find an available name with stat and then mkdir ", which is race-prone.请注意,“ git worktree add ”用于执行“使用 stat 然后mkdir查找可用名称”,这很容易出现竞争。
This has been fixed with Git 2.22 (Q2 2019) by using mkdir and reacting to EEXIST in a loop. Git 2.22(2019 年第二季度)已通过使用mkdir并在循环中对EEXIST做出反应来解决此问题。

See commit 7af01f2 (20 Feb 2019) by Michal Suchanek ( hramrach ) .请参阅Michal Suchanek ( hramrach )提交 7af01f2 (2019 年 2 月 20 日)。
(Merged by Junio C Hamano -- gitster -- in commit 20fe798 , 09 Apr 2019) (由Junio C Hamano -- gitster --提交 20fe798中合并,2019 年 4 月 9 日)

worktree : fix worktree add race worktree :修复worktree add种族

Git runs a stat loop to find a worktree name that's available and then does mkdir on the found name. Git 运行 stat 循环以查找可用的工作树名称,然后对找到的名称执行mkdir
Turn it to mkdir loop to avoid another invocation of worktree add finding the same free name and creating the directory first.将其转为mkdir循环以避免再次调用 worktree add 找到相同的空闲名称并首先创建目录。


Git 2.22 (Q2 2019) fixes the logic to tell if a Git repository has a working tree protects " git branch -D " from removing the branch that is currently checked out by mistake. Git 2.22(2019 年第二季度)修复了判断 Git 存储库是否有工作树保护“ git branch -D ”的逻辑。
The implementation of this logic was broken for repositories with unusual name, which unfortunately is the norm for submodules these days.对于具有不寻常名称的存储库,此逻辑的实现被破坏了,不幸的是,如今这已成为子模块的规范。

See commit f3534c9 (19 Apr 2019) by Jonathan Tan ( jhowtan ) .请参阅Jonathan Tan ( jhowtan )提交 f3534c9 (2019 年 4 月 19 日)。
(Merged by Junio C Hamano -- gitster -- in commit ec2642a , 08 May 2019) (由Junio C Hamano -- gitster --提交 ec2642a中合并,2019 年 5 月 8 日)

worktree : update is_bare heuristics工作is_bare worktree

When " git branch -D <name> " is run, Git usually first checks if that branch is currently checked out.当“ git branch -D <name> ”运行时,Git 通常首先检查该分支当前是否已签出。
But this check is not performed if the Git directory of that repository is not at " <repo>/.git ", which is the case if that repository is a submodule that has its Git directory stored as " super/.git/modules/<repo> ", for example.但是,如果该存储库的 Git 目录不在“ <repo>/.git ”中,则不会执行此检查,如果该存储库是一个子模块,其 Z0BCC70105AD279503E31FE7B3F4/module 存储为“ super/.git/modules/<repo> .git7B6” super/.git/modules/<repo> ”,例如。
This results in the branch being deleted even though it is checked out.这会导致分支被删除,即使它已被签出。

This is because get_main_worktree() in worktree.c sets is_bare on a worktree only using the heuristic that a repo is bare if the worktree's path does not end in " /.git ", and not bare otherwise.这是因为get_main_worktree()仅在工作树的路径未以“ /.git ”结尾时才使用启发式方法在工作worktree.c设置is_bare ,否则不会裸露。
This is_bare code was introduced in 92718b7 (" worktree : add details to the worktree struct", 2015-10-08, Git v2.7.0-rc0), following a pre-core.bare heuristic.这个is_bare代码是在92718b7 (“ worktree : add details to the worktree struct”, 2015-10-08, Git v2.7.0-rc0)中引入的,遵循pre-core.bare启发式。

This patch does 2 things:这个补丁做了两件事:

  • Teach get_main_worktree() to use is_bare_repository() instead, introduced in 7d1864c ("Introduce is_bare_repository() and core.bare configuration variable", 2007-01-07, Git v1.5.0-rc1) and updated in e90fdc3 ("Clean up work-tree handling", 2007-08-01, Git v1.5.3-rc4).get_main_worktree()改为使用is_bare_repository() ,在7d1864c中引入(“介绍 is_bare_repository() 和 core.bare 配置变量”,2007-01-07,Git v1.5.0-rc1)并在e90fdc3中更新(“清理工作” -树处理”,2007-08-01,Git v1.5.3-rc4)。
    This solves the " git branch -D <name> " problem described above.这解决了上面描述的“ git branch -D <name> ”问题。
    However...然而...
  • If a repository has core.bare=1 but the " git " command is being run from one of its secondary worktrees, is_bare_repository() returns false (which is fine, since there is a worktree available).如果存储库具有core.bare=1但“ git ”命令正在从其辅助工作树之一运行, is_bare_repository()返回 false (这很好,因为有可用的工作树)。
    And, treating the main worktree as non-bare when it is bare causes issues: for example, failure to delete a branch from a secondary worktree that is referred to by a main worktree's HEAD, even if that main worktree is bare.并且,当主工作树是裸的时将其视为非裸会导致问题:例如,无法从主工作树的 HEAD 引用的辅助工作树中删除分支,即使该主工作树是裸的。

In order to avoid that, also check core.bare when setting is_bare .为了避免这种情况,在设置is_bare core.bare
If core.bare=1 , trust it, and otherwise, use is_bare_repository() .如果core.bare=1 ,信任它,否则,使用is_bare_repository()


With Git 2.29 (Q4 2020), the " worktree " API offers a better determination of a worktree path.借助 Git 2.29(2020 年第四季度),“工作树” worktree可以更好地确定工作树路径。

See commit 918d8ff , commit 1c4854e , commit 246756f , commit 62573a5 (31 Jul 2020) by Eric Sunshine ( sunshineco ) .请参阅Eric Sunshine ( sunshineco ) 的commit 918d8ffcommit 1c4854ecommit 246756fcommit 62573a5 (2020 年 7 月 31 日)。
(Merged by Junio C Hamano -- gitster -- in commit 197253e , 10 Aug 2020) (由Junio C Hamano -- gitster --提交 197253e中合并,2020 年 8 月 10 日)

worktree : drop bogus and unnecessary path munging worktree :丢弃虚假和不必要的路径修改

Signed-off-by: Eric Sunshine签字人:Eric Sunshine

The content of .git/worktrees/<id>/gitdir must be a path of the form " /path/to/worktree/.git ". .git/worktrees/<id>/gitdir的内容必须是“ /path/to/worktree/.git ”形式的路径。
Any other content would be indicative of a corrupt " gitdir " file.任何其他内容都表明“ gitdir ”文件已损坏。

To determine the path of the worktree itself one merely strips the " /.git " suffix, and this is indeed how the worktree path was determined from inception.要确定工作树本身的路径,只需去掉“ /.git ”后缀,这确实是从一开始就确定工作树路径的方式。

However, 5193490442 (" worktree : add a function to get worktree details", 2015-10-08, Git v2.7.0-rc0 -- merge listed in batch #7 ) extended the path manipulation in a mysterious way.但是, 5193490442 (“ worktree :添加 function 以获取工作树详细信息”,2015-10-08,Git v2.7.0-rc0 - 以一种神秘的方式合并第 7 批中)扩展了路径操作。
If it is unable to strip " /.git " from the path, then it instead reports the current working directory as the linked worktree's path:如果它无法从路径中删除“ /.git ”,则它将当前工作目录报告为链接工作树的路径:

 if (,strbuf_strip_suffix(&worktree_path. "/;git")) { strbuf_reset(&worktree_path), strbuf_add_absolute_path(&worktree_path. ";"), strbuf_strip_suffix(&worktree_path. "/;"); }

This logic is clearly bogus;这个逻辑显然是假的; it can never be generally correct behavior.它永远不可能是普遍正确的行为。 It materialized out of thin air in 5193490442 with neither explanation nor tests to illustrate a case in which it would be desirable.它在5193490442中凭空出现,既没有解释也没有测试来说明它是可取的情况。

It's possible that this logic was introduced to somehow deal with a corrupt " gitdir " file, so that it returns some sort of meaningful value, but returning the current working directory is not helpful.引入此逻辑可能是为了以某种方式处理损坏的“ gitdir ”文件,以便它返回某种有意义的值,但返回当前工作目录没有帮助。 In fact, it is quite misleading (except in the one specific case when the current directory is the worktree whose " gitdir " entry is corrupt).事实上,这是非常具有误导性的(除了在当前目录是“ gitdir ”条目已损坏的工作树的一种特定情况下)。
Moreover, reporting the corrupt value to the user, rather than fibbing about it and hiding it outright, is more helpful since it may aid in diagnosing the problem.此外,向用户报告损坏的值,而不是撒谎并完全隐藏它,更有帮助,因为它可能有助于诊断问题。

Therefore, drop this bogus path munging and restore the logic to the original behavior of merely stripping " /.git ".因此,放弃这个虚假的路径修改并将逻辑恢复为仅剥离“ /.git ”的原始行为。

The git distribution comes with a contributed script called git-new-workdir . git发行版附带一个名为git-new-workdir 的贡献脚本 You would use it as follows:您可以按如下方式使用它:

git-new-workdir project-dir new-workdir branch

where project-dir is the name of the directory containing your .git repository.其中 project-dir 是包含.git存储库的目录的名称。 This scripts creates another .git directory with many symlinks to the original one except for files that cannot be shared (like the current branch), allowing you to work in two different branches.此脚本创建另一个.git目录,其中包含许多指向原始目录的符号链接,除了无法共享的文件(如当前分支),允许您在两个不同的分支中工作。

It sounds a bit fragile, but it's an option.这听起来有点脆弱,但这是一个选择。

I came across this question hoping for a solution I didn't find here.我遇到了这个问题,希望能找到我在这里找不到的解决方案。 So now that I did find what I needed, I decided to post it here for others.所以现在我确实找到了我需要的东西,我决定在这里发布给其他人。

Caveat: This is probably not a good solution if you need to edit multiple branches simultaneously, like OP states.警告:如果您需要同时编辑多个分支,例如 OP 状态,这可能不是一个好的解决方案。 It is for having multiple branches checked out simultaneously that you don't intend to edit.这是为了同时签出多个您打算编辑的分支。 (Multiple working directories backed by one.git folder.) (由一个.git 文件夹支持的多个工作目录。)

There were a few things I've learned since I came to this question the first time:自从我第一次提出这个问题以来,我学到了一些东西:

  1. What a " bare repository " is.什么是“裸仓库”。 It is essentially the contents of the .git directory, without being located in a working tree.它本质上是.git目录的内容,而不是位于工作树中。

  2. The fact that you can specify the location of the repo you are using (the location of your .git dir) on the command line with the git option --git-dir=您可以使用git选项--git-dir=在命令行上指定您正在使用的存储库的位置( .git目录的位置)

  3. The fact that you can specify the location of your working copy with --work-tree=您可以使用--work-tree=指定工作副本的位置这一事实

  4. What a "mirror repo" is.什么是“镜像回购”。

This last is a pretty important distinction.最后一点是一个非常重要的区别。 I don't actually want to work on the repo, I just need to have copies of different branches and/or tags checked out simultaneously.我实际上并不想处理repo,我只需要同时签出不同分支和/或标签的副本。 In actual fact, I need to guarantee that the branches don't end up different from my remote's branches.实际上,我需要保证分支最终不会与我的远程分支不同。 So a mirror is perfect for me.所以镜子对我来说是完美的。

So for my use case, I got what I needed by doing:所以对于我的用例,我得到了我需要的东西:

git clone --mirror <remoteurl> <localgitdir> # Where localgitdir doesn't exist yet
mkdir firstcopy
mkdir secondcopy
git --git-dir=<localgitdir> --work-tree=firstcopy checkout -f branch1
git --git-dir=<localgitdir> --work-tree=secondcopy checkout -f branch2

The big caveat about this is that there isn't a separate HEAD for the two copies.关于这一点的最大警告是两个副本没有单独的 HEAD。 So after the above, running git --git-dir=<localgitdir> --work-tree=firstcopy status will show all the differences from branch2 to branch1 as uncommitted changes - because HEAD is pointing at branch2.所以在上述之后,运行git --git-dir=<localgitdir> --work-tree=firstcopy status将显示从 branch2 到 branch1 的所有差异作为未提交的更改 - 因为 HEAD 指向 branch2。 (That's why I use the -f option to checkout , because I'm not actually planning to make any changes locally at all. I can checkout any tag or branch for any work-tree, as long as I use the -f option.) (这就是为什么我使用-f选项来checkout ,因为我实际上根本不打算在本地进行任何更改。只要我使用-f选项,我就可以检查任何工作树的任何标记或分支。 )

For my use case of having multiple checkouts co-existing on the same computer without needing to edit them , this works perfectly.对于我在同一台计算机上共存多个结帐而无需编辑它们的用例,这非常有效。 I don't know if there is any way to have multiple HEADs for the multiple work trees without a script such as is covered in the other answers, but I hope this is helpful to someone else anyway.我不知道是否有任何方法可以在没有脚本的情况下为多个工作树设置多个 HEAD,例如其他答案中所涵盖的脚本,但我希望无论如何这对其他人有帮助。

The only solution I can think of is to clone two directories and add them as remote repositories of each other.我能想到的唯一解决方案是克隆两个目录并将它们添加为彼此的远程存储库。 You can then keep pulling stuff from the changed one into the other without actually pushing anything to the remote repository.然后,您可以继续将内容从已更改的一个拉到另一个,而无需实际将任何内容推送到远程存储库。

I am assuming you want to have two working directories and not two clones of the remote because you don't want to push some branches to the remote.我假设您想要有两个工作目录而不是远程的两个克隆,因为您不想将一些分支推送到远程。 Otherwise, two clones of your remote would work just fine - you just need to do some pushes and pulls to keep all three in sync.否则,你的遥控器的两个克隆就可以正常工作 - 你只需要做一些推拉来保持所有三个同步。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM