无法硬链接gitconfig文件

7
我正在尝试创建一个git仓库来存储所有的点文件和配置文件。我的想法是简单地创建硬链接到我关心的所有文件,并将这些链接存储在它们自己的目录中,以便我可以将其转换为仓库。
然而,我遇到了一个小问题,就是我的~/.gitconfig文件。似乎每当我运行'git config'命令时,我创建的链接就不再指向正确的位置,例如,仓库中的文件不再正确更新。
以下是一个示例,使用shell和交互式ruby来确定文件的链接状态。
# Create the link
$ ln .gitconfig .conf_files/gitconfig  # Create the link

# The files are in fact linked
[1] pry(main)> File.identical?('.gitconfig', '.conf_files/gitconfig')
=> true

# Update the gitconfig file by running a 'git config' command
$ git config --global alias.last 'log -1 HEAD'

# The files are no longer linked.
[2] pry(main)> File.identical?('.gitconfig', '.conf_files/gitconfig')
=> false

我猜这与git编写.gitconfig文件的方式有关。有人知道为什么会发生这种情况吗?或者有没有创意的解决方法?

1
git config 会破坏硬链接。请使用符号链接代替。 - William Pursell
@William Pursell 如果我错了,请纠正我,但我认为git不识别符号链接? - Matt Garriott
2
将实际文件放入git存储库中,然后在$HOME中放置一个符号链接。git永远不会看到软链接。 - William Pursell
@WilliamPursell:Git将符号链接记录为符号链接,而不是指向的文件。 - Dietrich Epp
2
很遗憾,如果您将实际的~/.gitconfig文件设置为符号链接,那么当您运行git config命令时,git将简单地覆盖它,就像使用硬链接一样。 - Matt Garriott
@Matt,没关系。文件已更新,并运行git diff显示了更新。然后你可以提交更改。@Dietrich,git永远不会知道软链接的存在。 git看到的是该文件的硬链接(可能是唯一的链接),但当git读取/.gitconfig或bash读取/.bashrc时,它们会跟随到仓库中的文件。 - William Pursell
4个回答

6

尝试Eli Barzilay在他的评论中提供的解决方案,链接为:http://www.xxeo.com/archives/2010/02/16/dotfiles-in-git-finally-did-it.html:

所以我终于找到了一种方案,它兼顾了两者的优点:将repo放在子目录中,并添加一个配置选项“core.worktree”,将其设置为您的主目录。现在,当您位于主目录中时,您不再处于git repo中(因此第一个问题已经解决),而且您也不需要像第二种情况下那样处理易碎的符号链接。您仍然需要排除您不想版本化的路径(例如,“.git/info/exclude”技巧中的“*”),但这不是新问题。


这个方法非常好!它解决了每个路径都被识别为git命令的问题,避免了需要使用任何链接的问题,而且你不必在文件系统的根目录上弄乱。我只是将我的答案中.gitignore文件的内容移动到.conf_files/.git/info/exclude中,它就像魔法一样奏效了。非常感谢您! - Matt Garriott

2
这是完全正常的,事实上这是覆盖配置文件的推荐方式。Git会创建一个临时文件,写入配置,然后将新文件移动到旧文件上。这样,如果Git被中断,就不会出现不完整的配置文件(数据丢失)。
您可以编写一个脚本,将您的配置文件复制或链接到您的中央存储库中。

这就解释了为什么硬链接会断开,但我希望有一种更简单/更清晰的方法来保持文件相同。 - Matt Garriott
@MattGarriott:这里真正的问题是你试图使用Git来跟踪不能在Git仓库本身中的文件。这只是现今文件系统设计和Git设计的基本限制。我认为编写一个脚本是“简单而干净”的方法。毕竟,Git本身就是一堆脚本。另一种选择是让Git跟踪其仓库之外的文件--虽然这在技术上是可能的,但你需要了解Git的内部机制。 - Dietrich Epp
你说得完全正确,这就是为什么我决定从不同的角度来解决这个问题,我已经将我的新方案作为回答附上。感谢你们的解释和帮助! - Matt Garriott

0
感谢Dietrich Epp的回答和建议,我决定从不同的角度来解决这个问题,通过在文件系统的根目录创建存储库,并使用.gitignore仅跟踪我感兴趣的文件。
我的.gitignore文件现在看起来像这样:
/*

!/etc/
/etc/*

# etc files
!/etc/rc.conf
!/etc/asound.conf
!/etc/mercurial/

!/home/
!/home/matt/
/home/matt/*

# Home files
!/home/matt/.xinitrc
!/home/matt/.gitconfig
!/home/matt/.bashrc

# Vim files
!/home/matt/.vimrc
!/home/matt/.vim/
.netrwhist

除了不必将文件分别复制并保留在两个不同的位置外,这样做的好处是,如果需要,我可以轻松地还原更改,而无需手动复制文件。

感谢大家的帮助!


0

看看这个答案,也许会有帮助:

https://dev59.com/xG865IYBdhLWcg3wnP2a#3731139

同时,您考虑过反向链接吗?创建一个包含配置文件等内容的存储库,然后在实际使用文件的位置创建到存储库中的“真实”文件的硬链接。

6
硬链接是对称的。它们不会倒转,因为它们一开始就没有向前移动。 - Dietrich Epp
啊,那似乎有点小问题。 - wardd

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