Git 有多个工作目录?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6270193/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-10 11:07:48  来源:igfitidea点击:

Multiple working directories with Git?

git

提问by jtolds

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 clone 解决方案(默认情况下,它是硬链接共享对象,以及 --shared 选项,它使用原始存储库设置备用对象存储),但这些解决方案只会减少磁盘空间使用,尤其是在 --shared 的情况下,似乎充满了危险。

Is there a way to use one .git folder, and have two working directories backed by it? Or is Git hardcoded to have just one working directory checked out at any time?

有没有办法使用一个 .git 文件夹,并有两个工作目录由它支持?或者 Git 是硬编码的以便在任何时候都只检出一个工作目录?

回答by VonC

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 worktree

See commit 68a2e6aby Junio C Hamano (gitster).

看看提交68a2e6a通过JUNIOÇ滨野(gitster

The release note mentions:

发行说明中提到

A replacement for contrib/workdir/git-new-workdirthat 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. The new working directory is linked to the current repository, sharing everything except working directory specific files such as HEAD, index, etc. The git worktreesection adds:

A git repository can support multiple working trees, allowing you to check out more than one branch at a time.
With git worktree add, a new working tree is associated with the repository.

This new working tree is called a "linked working tree" as opposed to the "main working tree" prepared by "git init" or "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/worktreesdirectory.
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/.gitthe command git worktree add /path/other/test-next nextcreates:

  • the linked working tree in /path/other/test-nextand
  • also creates a $GIT_DIR/worktrees/test-nextdirectory (or $GIT_DIR/worktrees/test-next1if test-nextis already taken).

Within a linked working tree:

  • $GIT_DIRis set to point to this private directory (e.g. /path/main/.git/worktrees/test-nextin the example) and
  • $GIT_COMMON_DIRis set to point back to the main working tree's $GIT_DIR(e.g. /path/main/.git).

These settings are made in a .gitfile located at the top directory of the linked working tree.

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.pruneworktreesexpirein git config), or you can run git worktree prunein the main or any linked working tree to clean up any stale administrative files.

创建<path>并结帐<branch>到其中。新的工作目录链接到当前存储库,共享除工作目录特定文件(如 HEAD、索引等)之外的所有git worktree内容。该部分添加:

一个 git 存储库可以支持多个工作树,允许您一次检出多个分支。
使用git worktree add,新的工作树与存储库相关联。

这个新的工作树被称为“链接工作树”,而不是由“ git init”或“ git clone”准备的“主工作树”
一个存储库有一个主要的工作树(如果它不是一个裸存储库)和零个或多个链接的工作树。

细节:

每个链接的工作树在存储库目录中都有一个私有子目录 $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位于链接工作树顶部目录的文件中进行。

完成链接的工作树后,您可以简单地将其删除。
存储库中工作树的管理文件最终将被自动删除(参见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 submodulesis incomplete.
It is NOT recommended to make multiple checkouts of a superproject.

对子模块的支持不完整
不建议对一个超级项目进行多次签出。



Note: with git 2.7rc1 (Nov 2015) you are able to listyour worktrees.
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).
(Merged by Junio C Hamano -- gitster--in commit a46dcfb, 26 Oct 2015)

注意:使用 git 2.7rc1(2015 年 11 月),您可以列出您的工作树。
提交bb9c03b提交92718b7提交5193490提交1ceb7f9提交1ceb7f9提交5193490提交1ceb7f9提交1ceb7f9(2015年10月8日),提交92718b7提交5193490提交1ceb7f9提交1ceb7f9(2015年10月8日),提交5193490提交 1ceb7f9(2015 年 10 月 8 日),提交 1ceb7f9(2015 年 10 月 8 日),并提交 ac6c561(2015 年 10 月 2 日)作者:Michael Rappazzo ( rappazzo)
(由Junio C gitsterHamano合并-- --in commit a46dcfb,2015 年 10 月 26 日)

worktree: add 'list' command

'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.

worktree: 添加 ' list' 命令

' 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)

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.
  • Boolean attributes (like 'bare' and 'detached') are listed as a label only, and are only present if and only if the value is true.
  • An empty line indicates the end of a worktree

还有瓷器格式选项可用。

瓷器格式的每个属性都有一行。

  • 属性列有标签和值,由单个空格分隔。
  • 布尔属性(如 'bare' 和 'detached')仅作为标签列出,并且仅当且仅当值为 true 时才存在。
  • 空行表示工作树的结尾

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 manuallyupdate the gitdirfile.

注意:如果您移动工作树文件夹,则需要手动更新gitdir文件。

See commit 618244e(22 Jan 2016), and commit d4cddd6(18 Jan 2016) by Nguy?n Thái Ng?c Duy (pclouds).
Helped-by: Eric Sunshine (sunshineco).
(Merged by Junio C Hamano -- gitster--in commit d0a1cbc, 10 Feb 2016)

请参阅Nguy?n Thái Ng?c Duy ( ) 的commit 618244e(2016 年 1 月 22 日)和commit d4cddd6(2016 年 1 月 18 日。 帮助者:Eric Sunshine ( )(由Junio C Hamano合并-- --d0a1cbc 提交中,2016 年 2 月 10 日)pclouds
sunshineco
gitster

The new docin 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.
For example, if a linked working tree is moved to /newpath/test-nextand its .gitfile points to /path/main/.git/worktrees/test-next, then update /path/main/.git/worktrees/test-next/gitdirto reference /newpath/test-nextinstead.

如果移动链接的工作树,则需要更新gitdir条目目录中的“ ”文件。
例如,如果将链接的工作树移动到/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 anotherworking 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).
Helped-by: Eric Sunshine (sunshineco).
(Merged by Junio C Hamano -- gitster--in commit 4fca4e3, 13 Apr 2016)

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

branch -d: refuse deleting a branch which is currently checked out

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.

branch -d: 拒绝删除当前检出的分支

当前工作树检出分支时,禁止删除该分支。
然而,当分支仅被其他工作树检出时,错误删除成功。
使用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).
(Merged by Junio C Hamano -- gitster--in commit 741a694, 18 Apr 2016)

请参阅Kazuki Yamaguchi ( ) 的commit 18eb3a9(2016 年 4 月 8 日)和commit 70999e9commit 2233066(2016 年 3 月 27 日(由Junio C Hamano合并-- --commit 741a694,2016 年 4 月 18 日)rhenium
gitster

branch -m: update all per-worktree HEADs

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.

This is the current behavior, /path/to/wt's HEAD is not updated:

branch -m: 更新所有每个工作树的 HEAD

重命名分支时,目前只更新当前工作树的HEAD,但必须更新所有指向旧分支的工作树的HEAD。

这是当前行为,/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).
Suggested-by: Eric Sunshine (sunshineco).
(Merged by Junio C Hamano -- gitster--in commit 2c608e0, 28 Jul 2016)

提交080739b提交6d30862提交58142c0提交346ef53提交346ef53提交58142c0提交346ef53提交346ef53(2016年6月13日),以及提交984ad9e提交6835314(2016年6月3日)由Nguy 2 N泰伍2 C维战( pclouds)
推荐人:Eric Sunshine ( sunshineco)
(由Junio C gitsterHamano合并-- --commit 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 lockcommand, optionally specifying --reasonto explain why the working tree is locked.

<worktree>: If the last path components in the working tree's path is unique among working trees, it can be used to identify worktrees.
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.

如果链接的工作树存储在并非总是挂载的便携式设备或网络共享上,您可以通过发出git worktree lock命令来防止其管理文件被修剪,可选择指定--reason解释工作树被锁定的原因。

<worktree>:如果工作树路径中的最后一个路径组件在工作树中是唯一的,则可以使用它来标识工作树。
例如,如果您只需要在 " /abc/def/ghi" 和 " /abc/def/ggg"处工作树,那么 " ghi" 或 " def/ghi" 足以指向前一个工作树。



Git 2.13 (Q2 2017) add a lockoptionin commit 507e6e9(12 Apr 2017) by Nguy?n Thái Ng?c Duy (pclouds).
Suggested-by: David Taylor (dt).
Helped-by: Jeff King (peff).
(Merged by Junio C Hamano -- gitster--in commit e311597, 26 Apr 2017)

Git 2.13(2017 年第二季度)在Nguy?n Thái Ng?c Duy ( ) 的提交 507e6e9(2017 年 4 月 12日)中添加了一个lock选项。 推荐人:大卫·泰勒 ( )。 帮助者:杰夫·金 ( )(由Junio C Hamano合并-- --提交 e311597 中,2017 年 4 月 26 日)pclouds
dt
peff
gitster

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' --lockis the equivalent of git worktree lockafter git worktree add, but without race condition.

所以git worktree add' --lock是相当于git worktree lockgit worktree add,但没有竞争条件。



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 年第 3 季度)添加了一个 " --quiet" 选项,使 " git worktree add" 不那么冗长。

See commit 371979c(15 Aug 2018) by Elia Pinto (devzero2000).
Helped-by: Martin ?gren , Duy Nguyen (pclouds), and Eric Sunshine (sunshineco).
(Merged by Junio C Hamano -- gitster--in commit a988ce9, 27 Aug 2018)

请参阅Elia Pinto ( ) 的提交 371979c(2018 年 8 月 15 日。 帮助者:Martin?gren、Duy Nguyen ( )Eric Sunshine ( )(由Junio C Hamano合并-- --commit a988ce9,2018 年 8 月 27 日)devzero2000
pcloudssunshineco
gitster

worktree: add --quietoption

Add the '--quiet' option to git worktree, as for the other gitcommands.
'add' is the only command affected by it since all other commands, except 'list', are currently silent by default.

worktree: 添加--quiet选项

对于其他命令,将 ' --quiet' 选项添加到。 “ ”是唯一受其影响的命令,因为除“ ”之外的所有其他命令当前默认处于静默状态。git worktreegit
addlist



Note that "git worktree add" used to do a "find an available name with stat and then mkdir", which is race-prone.
This has been fixed with Git 2.22 (Q2 2019) by using mkdirand reacting to EEXISTin a loop.

请注意,“ git worktree add”用于“使用 stat 查找可用名称,然后mkdir”,这很容易发生竞争。
这已在 Git 2.22(2019 年第二季度)中通过循环使用mkdir和反应得到修复EEXIST

See commit 7af01f2(20 Feb 2019) by Michal Suchanek (hramrach).
(Merged by Junio C Hamano -- gitster--in commit 20fe798, 09 Apr 2019)

请参阅Michal Suchanek ( ) 的commit 7af01f2(20 Feb 2019 )(由Junio C Hamano合并-- --2019 年 4 月 9 日提交 20fe798 中hramrach
gitster

worktree: fix worktree addrace

Git runs a stat loop to find a worktree name that's available and then does mkdiron the found name.
Turn it to mkdirloop to avoid another invocation of worktree add finding the same free name and creating the directory first.

worktree: 修复worktree add种族

Git 运行一个 stat 循环来查找可用的工作树名称,然后mkdir在找到的名称上执行。
将其转为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.
The implementation of this logic was broken for repositories with unusual name, which unfortunately is the norm for submodules these days.

Git 2.22(2019 年第 2 季度)修复了判断 Git 存储库是否具有工作树的逻辑,以保护“ git branch -D”免于删除当前错误检出的分支。
对于具有不寻常名称的存储库,此逻辑的实现被破坏,不幸的是,这已成为如今子模块的规范。

See commit f3534c9(19 Apr 2019) by Jonathan Tan (jhowtan).
(Merged by Junio C Hamano -- gitster--in commit ec2642a, 08 May 2019)

请参阅Jonathan Tan ( ) 的commit f3534c9(2019 年 4 月 19 日(由Junio C Hamano合并-- --ec2642a 提交中,2019 年 5 月 8 日)jhowtan
gitster

Code Pull requests 178 Insights

worktree: update is_bareheuristics

When "git branch -D <name>" is run, Git usually first checks if that branch is currently checked out.
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.
This results in the branch being deleted even though it is checked out.

This is because get_main_worktree()in worktree.csets is_bareon 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.
This is_barecode was introduced in 92718b7("worktree: add details to the worktree struct", 2015-10-08, Git v2.7.0-rc0), following a pre-core.bareheuristic.

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).
    This solves the "git branch -D <name>" problem described above.

However... If a repository has core.bare=1but 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).

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.

In order to avoid that, also check core.barewhen setting is_bare.
If core.bare=1, trust it, and otherwise, use is_bare_repository().

代码拉取请求 178 个见解

worktree: 更新is_bare启发式

当“ git branch -D <name>”运行时,Git 通常首先检查该分支当前是否已检出。
但是,如果该存储库的 Git 目录不在“ <repo>/.git”处,则不会执行此检查,例如,如果该存储库是其 Git 目录存储为“ super/.git/modules/<repo>”的子模块,就会出现这种情况。
这会导致分支被删除,即使它被检出。

这是因为get_main_worktree()worktree.cis_bare只使用启发式,一个回购是裸露的,如果worktree的路径不以“结束worktree /.git”,否则不裸露。
is_bare代码在92718b7(“ worktree:向工作树结构添加详细信息”,2015-10-08,Git v2.7.0-rc0)中引入,遵循pre-core.bare启发式。

这个补丁做了两件事:

  • Teach get_main_worktree()to use is_bare_repository(),在7d1864c 中引入(“Introduce is_bare_repository() and core.bare configuration variable”,2007-01-07,Git v1.5.0-rc1)并在e90fdc3 中更新(“清理工作树处理”,2007 -08-01,Git v1.5.3-rc4)。
    这解决了上述“ git branch -D <name>”问题。

但是...如果存储库具有core.bare=1git正在从其辅助工作树之一运行“ ”命令,则is_bare_repository()返回 false(这很好,因为有可用的工作树)。

并且,将主工作树视为非裸会导致问题:

例如,无法从主工作树的 HEAD 引用的辅助工作树中删除分支,即使该主工作树是空的。

为了避免这种情况,请core.bare在设置时检查is_bare
如果core.bare=1,相信它,否则,使用is_bare_repository()

回答by adl

The gitdistribution comes with a contributed scriptcalled git-new-workdir. You would use it as follows:

git发行版带有一个名为git-new-workdir. 您可以按如下方式使用它:

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

where project-dir is the name of the directory containing your .gitrepository. This scripts creates another .gitdirectory 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.

其中 project-dir 是包含您的.git存储库的目录的名称。.git除了不能共享的文件(如当前分支)外,此脚本创建另一个目录,其中包含许多指向原始目录的符号链接,允许您在两个不同的分支中工作。

It sounds a bit fragile, but it's an option.

这听起来有点脆弱,但它是一种选择。

回答by Wildcard

I came across this question hoping for a solution I didn't find here. So now that I didfind what I needed, I decided to post it here for others.

我遇到了这个问题,希望能找到我在这里找不到的解决方案。所以现在我确实找到了我需要的东西,我决定在这里发布给其他人。

Caveat: This is probably not a good solution if you need to editmultiple branches simultaneously, like OP states.It is for having multiple branches checked outsimultaneously that you don'tintend to edit. (Multiple working directories backed by one .git folder.)

警告:如果您需要同时编辑多个分支,例如 OP 状态,这可能不是一个好的解决方案。它用于同时签出打算编辑的多个分支。(多个工作目录由一个 .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 .gitdirectory, without being located in a working tree.

  2. The fact that you can specify the location of the repo you are using (the location of your .gitdir) on the command line with the gitoption --git-dir=

  3. The fact that you can specify the location of your working copy with --work-tree=

  4. What a "mirror repo" is.

  1. 什么是“裸仓库”。它本质上是.git目录的内容,而不是位于工作树中。

  2. 您可以使用选项.git在命令行上指定正在使用的存储库的位置(目录的位置)这一事实git--git-dir=

  3. 您可以使用以下命令指定工作副本的位置 --work-tree=

  4. 什么是“镜像回购”。

This last is a pretty important distinction. I don't actually want to workon the repo, I just need to have copies of different branches and/or tags checked out simultaneously. In actual fact, I need to guarantee that the branches don'tend up different from my remote's branches. So a mirror is perfect for me.

最后一个是非常重要的区别。我实际上并不想在 repo上工作,我只需要同时检出不同分支和/或标签的副本。实际上,我需要保证分支最终不会与我的远程分支不同。所以镜子对我来说是完美的。

So for myuse 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. So after the above, running git --git-dir=<localgitdir> --work-tree=firstcopy statuswill show all the differences from branch2 to branch1 as uncommitted changes - because HEAD is pointing at branch2. (That's why I use the -foption 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 -foption.)

关于这一点的重要警告是,这两个副本没有单独的 HEAD。所以在上述之后,运行git --git-dir=<localgitdir> --work-tree=firstcopy status会将所有从 branch2 到 branch1 的差异显示为未提交的更改 - 因为 HEAD 指向 branch2。(这就是我使用-fto 选项的原因checkout,因为我实际上根本不打算在本地进行任何更改。只要我使用该-f选项,我就可以检查任何工作树的任何标签或分支。)

For my use case of having multiple checkouts co-existing on the same computer withoutneeding 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,但我希望这对其他人有帮助。

回答by vhallac

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.

我假设您想要两个工作目录而不是远程的两个克隆,因为您不想将某些分支推送到远程。否则,你的遥控器的两个克隆就可以正常工作——你只需要做一些推拉来保持所有三个同步。