第0章:创建工作环境

基础知识

  • Git是一个著名的版本控制软件。它将软件的版本(代码+配置+测试+……)存放在一种特殊的数据库(Git repo)中。通过执行一些命令用户可以对数据库中的软件的版本进行增删改查等操作。

  • 在绝大多数情况下,Git repo的具体形式是硬盘上的一个文件夹。

  • 为了方便用户操作,每一个repo都可以配套一个worktree(但是至多只能有一个,可以没有)。worktree也是一个硬盘上的文件夹,它将和repo配合使用。

  • 为了方便多个repo之间共享数据,一个repo可以放弃所有对象(第1章)和绝大部分引用(第2章)等信息的所有权,将其全权托管给另一个repo。这种所谓链接只能在同一台计算机上实现。

    • 很多人认为一个repo可以有多个worktree,严格意义上讲其实是有好多个repo都链接到了同一个repo,每一个小repo贡献一个worktree,看起来是一个大repo有多个worktree的样子。

创建Git repo并选配worktree

Lv0

# Git repo以.git结尾只是惯例
mkdir the-repo.git
# 所有的Git repo都必须包括objects文件夹,用来保存对象
mkdir the-repo.git/objects
# 所有的Git repo都必须包括refs文件夹,用来保存普通引用
mkdir the-repo.git/refs
# 所有的Git repo都必须包括HEAD文件(这是一个特殊引用)
# 但是HEAD指向的目标不一定需要真实存在
# 在初始化时指向refs/heads/master只是惯例
echo 'ref: refs/heads/master' > the-repo.git/HEAD

至此一个最简单的Git repo创建完毕,采用git symbolic-ref(Lv2)检验是否创建成功:

现在添加worktree:

采用git status(Lv3)检验是否创建成功:

每次调用git命令都需要手工指定repo和worktree的位置非常麻烦。 绝大多数情况下,worktree和repo是一一对应的。 为了简化命令行调用方式,可以在worktree下添加.git文件:

这样的话Git就有办法根据worktree的位置找到repo的位置了。 然而非常遗憾的是,以下命令并不能成功:

原因是--work-tree必须和--git-dir配合使用。 解决办法就是cd过去:

另外一种办法是使用-C,表示先执行cd再执行git

注意cd进repo有时会报错,因为目前没有任何办法从repo找到worktree, 而一部分命令必须要有worktree才能正常工作(比如git status):

再进一步,如果希望避免使用绝对路径(repo移动了位置依然可以找到), 可以把repo放在worktree里面:

Lv3

日常创建repo、不选配worktree:

日常创建repo、选配worktree、把repo放在worktree里面:

日常创建repo、选配worktree、把repo和worktree分开放置:

添加新repo并链接到原repo,以实现“一个repo多个worktree”

Lv0

至此一个最简单的小repo创建完毕,采用git symbolic-ref(Lv2)检验是否创建成功:

和普通repo一样,添加worktree非常简单:

采用git status(Lv3)检验是否创建成功:

给小repo简化命令行调用方式完全相同:

现在小repo知道大repo的存在,但是大repo却不知道小repo的存在。 这不太合理。为此需要登记一下小repo的位置。 这样做的好处是git worktree list(Lv3)中可以正确地列举出小repo。

注意:如果没有遵循惯例把小repo放在大repo的worktrees/xxx位置, 那么gitdir文件还是必须往同样的位置去放,即便那里已经不是小repo了:

可以看到,虽然不在常规位置的小repo能够被成功识别, 但是git worktree list却无法正确列出其HEAD的内容。

Lv3

使用git worktree add可以添加小repo并选配worktree。 然而该命令至少需要一个commit对象才能正常工作。 这里就不演示了。 该命令语法是:

此处的--no-checkout是用来指示是否要在创建完worktree以后执行git restore -W。参见第3章。

删除小repo

Lv0

Lv3

基于别的repo创建新的repo

除了创建空白repo以外,还有一种方法是基于另一个repo创建新的repo。这个功能非常有用:GitHub上有很多repo,如果能够直接将其复制下来,或者说基于它创建自己的repo,那么就能够在别人的基础之上进行修改了。 这个功能涉及到远程文件传输,因此在第5章中会详细介绍。

总结

(以下均为Lv3)

  • 创建空repo,选配worktree

    • git init --bare <repo> - 不要worktree

    • git init --separate-git-dir <repo> <worktree>

    • git init <worktree> - repo在<worktree>/.git

  • “单”repo多worktree

    • git worktree list

    • git worktree add [--no-checkout] <worktree> <commit-ish>

    • git worktree prune

扩展阅读

gitrepository-layout

最后更新于

这有帮助吗?