我该如何使用Git跟踪单个文件的版本?

13

假设我有一个名为foo.txt的单个文件,我想用Git管理它,并且我不想将它移动到自己的目录中,例如/Users/me/Documents,该目录还有许多其他文件我不想与foo.txt一起包含在仓库中。这种操作是否可行?

我尝试创建了一个裸仓库(因此它不会被命名为.git):

git init --bare .foo.txt

我计划通过在info/exclude文件中添加类似以下内容来排除除foo.txt之外的所有内容:

*
!foo.txt

但我遇到的问题是,我甚至不能执行git status,因为似乎没有办法传入非标准替换的.git目录。

使用普通的.git目录行不通,因为它将限制我仅对该文件进行版本控制,或者强迫我在同一存储库中包含任何其他文件,而我希望能够在其自己的存储库中对该目录中的其他文件进行版本控制。

我意识到这不是Git设计用例,但由于它是我已经熟悉的强大工具,如果有方法可以这样做,我更愿意使用它而不是其他工具。


4
你能否将foo.txt作为符号链接到包含git仓库和真实文件的目录中? - Daenyth
我想做相反的事情(从带有 .git 目录的普通仓库中建立到 foo.txt 的符号链接),就在我提交问题的时候。我尝试了一下,但似乎不起作用,但我猜只是因为我在一个安装了 Git Bash 的 Windows 系统上操作。 (是啊,企业标准之类的废话)。我还没有在我的 MacBook Air 上测试过。 - iconoclast
1
https://gist.github.com/ 为每个文件使用一个仓库。这与@Daenyth建议的想法相同,只需将符号链接添加到您希望它位于的文件系统即可。 - jdi
1
@jdi: 当您克隆一个Gist时,您会得到一个目录。此外,Gist可以包含多个文件,只是它们通常(存储库/包含的目录)包含单个文件。 - Fred Foo
1
@larsmans:我理解。我只是指出这是一个生产示例,说明如何对单个文件进行版本跟踪,因为这就是GitHub所做的。显然,您可以在其中放置更多文件。无论如何,您都需要在存储库目录中放置一个文件。 - jdi
显示剩余8条评论
4个回答

8

如果您首先为该文件初始化git存储库,则可以完全按照自己的意愿进行操作:

git init --bare .foo.txt

然后像这样运行git:

git --git-dir=.foo.txt --work-tree=. status

将第二个命令的第一部分别名为git-foo,然后您就可以开始了。


不是创建 git-foo,我将创建一个通用函数,它可以同样适用于 foo.txtbar.csvbaz.yaml - iconoclast
2
function version() { prefix='.'; filename="$1"; shift; git --git-dir="${prefix}${filename}" --work-tree=. "$@"; } - iconoclast
1
然后你可以执行 version foo.txt add . (其中 . 表示你已经编辑了 .foo.txt/info/exclude,所以它只是代表 foo.txt),以及 version foo.txt status 和几乎任何你想要的 Git 命令。 - iconoclast
这对我没用。它只是打印了简短的帮助手册“usage: git [...”。 - aderchox
1
@aderchox 你可能没有先初始化存储库。我的原始答案假设如果你在做这样的特殊操作,你应该知道如何做,但为了明确起见,我已经编辑了答案以包括初始化步骤。祝玩得愉快!=) - wjl

5
如何使用 .gitignore 文件创建应编辑的文件过滤器。此解决方案避免了在 Windows 上不受支持的硬链接。
例如以下文件:
$ cat .gitignore
*
!data.xml

配置git忽略除"data.xml"之外的所有文件。


是的,但你把.gitignore文件放在哪里呢?如果你把它放在带有该文件的目录中,那么你就无法跟踪该目录中的任何其他文件。 - iconoclast
@iconoclast 忽略文件已提交到GIT存储库中。您想要一种机制来对一个文件进行版本控制。这种方法意味着.gitignore文件列出了那些符合版本控制条件的文件。一个存储库一个文件...好吧,这不是GIT的工作方式,我不确定为什么您希望以这种方式进行操作。也许可以使用旧的版本控制系统,比如RCS? :-) - Mark O'Connor
这并不是 Git 的正常用法,但正如新接受的答案所示,它是可能的。而且,正如我在问题中所说的,我知道这不是正常的用法,但如果可能的话,我宁愿使用 Git。我宁愿使用我熟悉的工具,而不是学习 RCS(即使它非常简单)。这样,如果需要,我就可以拥有 Git 的全部功能。我可以理解为什么你可能更喜欢 RCS,但争论哪种方法更好是没有意义的,因为这不是本网站或本问题的重点。 - iconoclast
我使用它来对/etc中的系统范围gitconfig进行版本控制,这是一个简单的解决方案。 - Timo

3

我认为你最好的选择是在一个单独的目录中创建一个存储库,并在其中为每个要包含的文件创建一个硬链接:

mkdir some_repo
cd some_repo
git init
ln path/to/file file
# add & commit

我看不出来这个程序在Unix系统上为什么不能正常工作。但是很遗憾,在Windows上运行Git Bash shell时,硬链接并不能真正地起作用。我认为在Windows上唯一的解决方案就是反复将原始文件复制到目录中,然后提交它。 - iconoclast
这是个好主意!谢谢你! - os11k

1

我最方便的方式是在单独的目录中跟踪存储库中的单个文件。

创建一个目录以存储git存储库。

mkdir my-repo-path

前往工作树目录(您想要的文件所在的位置)

cd my-worktree-path

my-repo-path的隐藏子目录.git中初始化一个单独的仓库。

git init --separate-git-dir my-repo-path\.git

随着单独的代码库,git在工作树目录中创建了一个隐藏文件.git。如果您愿意,可以将其删除(如果您打算在某些单独的代码库中单独跟踪其他文件,则可能会有用)。
del /AH .git

在任何文本编辑器中打开文件my-repo-path\.git\info\exclude,并在末尾添加以下行(其中foo.txt是您想跟踪的文件):
*
!foo.txt

在命令提示符中进入git仓库并添加将要提交的内容。
cd my-repo-path\.git
git add .
git commit

添加远程源并推送主分支,同时向其添加上游(跟踪)引用。
git remote add origin <url>
git push -u origin master

接下来,您将从Git存储库目录中添加以下提交(请参见倒数第二步骤)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接