我可以将.git文件夹存储在我想跟踪的文件之外吗?

我有一个不寻常的想法,使用git作为备份系统。 所以我们可以说我有一个目录./backup/myfiles,我想用git来支持它。 为了保持干净,我不想在myfiles文件夹中有一个.git目录,所以我想我可以创build./backup/git_repos/myfiles。 从看git文档,我试过这样做:

$ cd backup/myfiles $ mkdir ../git_repos/myfiles $ git --git-dir=../git_repos/myfiles init Initialized empty Git repository in backup/git_repos/myfiles/ $ git --git-dir="../git_repos/myfiles/" add foo fatal: pathspec 'foo' did not match any files 

你可以看到我到达那里的错误消息。 我究竟做错了什么?

 git --git-dir=../repo --work-tree=. add foo 

这将做你想做的事情,但是当你必须使用每一个你使用的git命令来指定它的时候,这显然会很糟糕。

你可以导出GIT_WORK_TREE=.GIT_DIR=../backup ,Git会在每个命令中select它们。 尽pipe如此,这只能让你在每个shell的单个仓库中工作。

我宁愿build议将.git目录符号链接到其他位置,或者从主备份目录创build.git目录的符号链接。

您只需确保存储库知道工作树在哪里,反之亦然。

要让存储库知道工作树在哪里,请设置configuration值core.worktree 。 为了让工作树知道它的git目录是什么,添加一个名为.git(不是文件夹!)的文件并添加一行

 gitdir: /path/to/repo.git 

因为git 1.7.5 init命令为此学习了一个额外的选项。

您可以使用初始化一个新的单独的存储库

 git init --separate-git-dir /path/to/repo.git 

这将初始化独立目录中的git存储库,并将.git文件添加到当前目录中,该目录是新存储库的工作目录。

以前到1.7.5,你必须使用稍微不同的参数,并自己添加.git文件。

要初始化单独的存储库,以下命令将工作树与存储库相链接:

 git --git-dir=/path/to/repo.git --work-tree=. init && echo "gitdir: /path/to/repo.git" > .git 

您当前的目录将是工作树,git将使用/path/to/repo.git的存储库。 init命令将自动设置core.worktree值,与--git-dir参数一起指定。

你甚至可以为此添加一个别名:

 [alias] initexternal = !"f() { git --work-tree=. --git-dir=\"$1\" init && echo \"gitdir: $1\" >> .git; }; f" 

在只读工作目录上使用git版本控制

有了以上的知识,你甚至可以设置工作目录的git版本控制,而无需写入权限。 如果你在每一个git命令中使用了--git-dir ,或者从版本库(而不是工作目录)执行每--git-dir命令,你可以省略.git文件,因此不需要在工作目录中创build任何文件。 另请参阅青less狮的答案

git init (和git clone )的--separate-git-dir选项可以用来在我的git版本( 1.7.11.3 )上完成这个1.7.11.3 。 该选项将git存储库与工作树分开,并在工作树的根目录下创build文件系统不可知的git符号链接(以名为.git的文件forms)。 我认为结果和尼克斯的答案是一致的。

 git init --separate-git-dir path/to/repo.git path/to/worktree 

传统的做法是将一个名为git仓库的目录命名为git仓库,该仓库的工作树位置非常不寻常,带有.git扩展名,就像裸仓库一样。

 mkdir ../git_repos/myfiles.git 

如果你在init时提供了--work-tree选项,那么这将会自动设置core.worktreeconfigurationvariables,这意味着一旦你指定了git目录,git就会知道在哪里find工作树。

 git --git-dir=../git_repos/myfiles.git --work-tree=. init 

但是你也可以在事后设置这个variables。

 git --git-dir=../git_repos/myfiles.git config core.worktree "$(pwd)" 

一旦你完成了这个,add命令应该按照预期工作。

 git --git-dir=../git_repos/myfiles.git add foo 

我发现把niks的答案中使用的--work-tree--git-dir目录颠倒过来更简单一些:

 $ cd read_only_repos $ git --work-tree=/some/readonly/location/foo/ --git-dir=foo init $ cd foo $ git status On branch master Initial commit Untracked files: (use "git add <file>..." to include in what will be committed) .file_foo bar ... 

这种方法有两个好处:

  • 它不需要任何命令行选项或.git文件。 您只需从存储库的根目录中正常运行。
  • 它允许您即使不拥有文件系统也可以对文件系统进行版本pipe理。 Git只会写入存储库位置。

我遇到的唯一的警告是,而不是使用.gitignore文件,你编辑info/exclude

然后,您可以使用存储库read_only_repos/foo作为您自己的存储库中的远程,即使原始文件不受版本控制。

在回购中使用git

 cd ./backup/git_repos/myfiles git init --bare git config core.worktree ../myfiles git config core.bare false 

从现在开始,你可以在./backup/git_repos/myfiles目录下使用git ,而不需要设置任何环境variables或者附加参数。

假设你的myfiles目录已经存在,并有一些内容,你可以住这个:

 cd ~/backup git init git add myfiles 

.git目录将在backup ,而不是在myfiles

你可以用类似的方式创build一个“nodgit”脚本(没有Dot GIT)

 #!/bin/sh gits=/usr/local/gits x=`pwd` testdir() {( cd $1; pwd; )} while [ "$x" != "/" ]; do y=`echo $x|sed -e "s/\//__/g"` if ([ -d "$gits/$y" ]); then export GIT_DIR="$gits/$y" export GIT_WORK_TREE="$x" if ([ "$1" = "nodinit" ]); then mkdir -p "$GIT_DIR" git init --bare; exit $? elif ([ "$1" = "shell" ]); then bash; exit $? else exec git "$@" fi fi x=`testdir "$x/.."` done 

你可以调用nodgit来代替git,它会根据需要通过寻找一个git repo来设置variables。 例如,假设您在/ usr / local / gits / __ home__foo_wibbles中有(裸)回购,并且您位于/ home / foo / wibbles /中,则会find正确的工作目录(/ home / foo / wibbles)和回购。

哦,你也可以使用“nodgitshell”得到一个正确的瓦尔设置的shell,所以你可以使用普通的旧Git命令。

我创build了看起来像的脚本

〜/斌/ git的斜线:

 #!/usr/bin/sh export GIT_DIR=/home/Version-Control/cygwin-root.git/ export GIT_WORK_TREE=/ git --git-dir=$GIT_DIR --work-tree=$GIT_WORK_TREE "$@" exit $? 

使用–git_dir = $ GIT_DIR是多余的,但是提醒我也可以在脚本之外设置环境variables。

上面的例子用于跟踪对cygwin系统文件的本地更改。

可以为任何需要此function的重大项目制作一个这样的脚本 – 但/无/.git是我的主要用途。

如果你消除了冗余,上面的内容足够小,可以构成shell别名或者函数。

如果我经常这样做,我会恢复工作空间的存储库映射

 "Boxes, Links, and Parallel Trees: Elements of a Configuration Management System", in Workshop Proceedings of the Software Management Conference. 1989. 

其最接近的现代对应物是Perforce映射或观点 ,支持部分结账以及非工作区和回购的托pipe。