我如何制作一个 git 挂钩来修改然后镜像一个 git 存储库?

How do I make a git hook for modifying then mirroring a git repository?

我的点文件 here 有一个 GitHub 存储库。

它包含一个 installdotfiles.sh 脚本,用于从 GitHub 安装点文件。我想在 GitLab 上有另一个 git 存储库用于备份(以及非常酷的自定义语法高亮 :P),镜像此存储库,除了 运行 宁 shell 存储库上的命令:

grep -rl raw.githubusercontent . | 
      xargs sed -i ''
     's/raw.githubusercontent/gitlab/g'; grep -rl 'dotfiles/master' . |
      xargs sed -i '' 's/dotfiles\/master/dotfiles\/raw\/master/g'

将指向 Github 的链接替换为指向 GitLab 的相应链接。

基本上,如果我推送到我的 GitHub 点文件存储库,我会自动更新我的 GitLab 存储库,除了 运行 存储库中的脚本首先,所以我让我的 GitLab 存储库包含 GitLab 链接。

我将如何实现这样的钩子?

我听说这可以使用 Git Hooks 来实现,但是我不熟悉它们,并且阅读它们,我不完全理解这样的事情是如何完成的。

P.S 如果它可以双向工作就更好了 - 所以当我推送到 GitLab 时,GitHub 将 运行 一个不同的脚本来替换 GitLab 链接与 GitHub 链接,因此每当我推送到其中一个时,两者都会相应更新。

How would I implement such a hook?

您可以选择任何您喜欢的挂钩并检查文件中的链接。

例如,您可以使用类似这样的东西,并在 if 条件之后添加您的脚本行。

pre-receive hook

#!/bin/sh

# Check to see if this is the first commit in the repository or not
if git rev-parse --verify HEAD >/dev/null 2>&1
then
    # We compare our changes against the previous commit
    against=HEAD^
else
    # Initial commit: diff against an empty tree object
    against=4b825dc642cb6eb9a060e54bf8d69288fbee4904
fi

# Redirect output to screen.
exec 1>&2

# Get the list of files which were commits
# assuming the other files are already contains the right values and does not need to be updated
files = $(git diff-tree -r --name-only $against )

# ... do whatever you want to do with the files

P.S it would be nice if it works both ways - so when I push to GitLab, GitHub will run a different script that replaces GitLab links with GitHub links, so that whenever I push to one, both update accordingly.

设置 2 个挂钩,我在每个存储库上设置正确的链接,每个存储库上都有正确的值。


另一种不使用钩子的方法:

如果您可以在客户端使用本地代码,则可以在 git:

中使用此功能

It turns out that you can write your own filters for doing substitutions in files on commit/checkout. These are called clean and smudge filters.

在这里阅读所有相关内容:
https://git-scm.com/book/en/v2/Customizing-Git-Git-Attributes#Keyword-Expansion

最简单的方法是让您的脚本 installdotfiles.sh 使用一个变量,该变量是您根据要获取文件的存储库设置的(在调用脚本之前)。

例如:

origin=github curl https://raw.githubusercontent.com/thepiercingarrow2/dotfiles/master/installdotfiles.sh | sh
# or
origin=gitlab curl https://gitlab.com/thepiercingarrow2/dotfiles/raw/master/.bash_profile | sh

这意味着您的脚本包含一个简单的测试:

remote="raw.githubusercontent.com/thepiercingarrow2/dotfiles"
if [[ "${origin}" == "gitlab" ]]; then
   remote="gitlab.com/thepiercingarrow2/dotfiles/raw"
fi

#bash_profile
curl -# https://${remote}/master/.bash_profile > ~/.bash_profile

换句话说,你真的不需要git钩子。任何一种。