Git Remote 添加位于 Windows 上的远端分支

398 阅读2分钟

本意是想单纯地从一台机器 git push 到另一台用,但操作起来颇为扭曲。此文作为记录。

Git 支持四种 remote url 协议:file http ssh git。本文试用了 file ssh git 三种。

参见 git-scm.com/book/en/v2/…

通过 SMB 共享

远端启用”网络文件和文件夹共享“,将目录共享出去。如共享了 "src" 有一个 git repo "src/a.git"

本地

# 四个反斜杠一个都不能少 :)
git remote set-url pc2 "file:////hostname/src/a.git

通过 Win32-OpenSSH

配置 Win32-OpenSSH

需要 Win10 及以上系统。

在本地机器上安装可选功能 "OpenSSH Client";在远端机器上安装可选功能 "OpenSSH Server" 并启用服务 "sshd"。

参考 docs.microsoft.com/en-us/windo…

对 server 而言,目前 Win32-OpenSSH 只能设置一个全局的 DefaultShell 而不能分用户设置,默认是 cmd.exe 。本文不做修改。

如果要登录的是 server 的管理员用户,Win32-OpenSSH 不接受 ~/.ssh/authorized_keys,而使用 C:\ProgramData\ssh\administrators_authorized_keys。而且也会以管理员权限启用 shell。

参考 docs.microsoft.com/en-us/windo…

Win32-OpenSSH 套用了 Windows 用户权限体系,需要确保:

  • server 的 C:\ProgramData\ssh\administrators_authorized_keys 只有管理员可读写。
  • client 的 ~/.ssh/config 及各私钥只有当前用户可读写。

经测试权限可以设为如下样式:(需要管理员权限运行)

# 禁用继承并移除继承来的权限(r),给予 当前用户 SYSTEM Administrators 全量权限(F)
icacls.exe "C:\ProgramData\ssh\administrators_authorized_keys" /inheritance:r /grant "$(whoami):F" /grant "Administrators:F" /grant "SYSTEM:F"

# 此外,设置当前用户为所有者
icacls.exe "$HOME\.ssh\config" /setowner "$(whoami)" /inheritance:r /grant "$(whoami):F" /grant "Administrators:F" /grant "SYSTEM:F"

icacls 用法参考 docs.microsoft.com/en-us/windo…

接下来可以 ssh 连上去试一下了。

Git

还需要一些知识,不然会迷惑该如何使用。如:不在 C 盘怎么办?

# 有一个目录 "D:\src\a.git\"
git remote set-url pc2 "ssh://username@hostname/d/src/a.git"

我们需要知道,Git 使用 ssh$env:GIT_SSH_COMMAND 指定的命令建立连接,然后会在远端运行命令 git-receive-pack '/d/src/a.git' 来交互。

然而,Git on Windows 默认不暴露 git-receive-pack.exe,直接暴露它也不可用,因为它需要在 git-bash 里运行(本质是需要 msys2-mingw64 环境)。

可以借用 scoop.sh 项目的 shim exe 来”转发“。从 $HOME/scoop/shims/ 里随便复制一个,或者从 github.com/71/scoop-be… 下载。

$env:PATH 里添加一个目录(或者选择已有的一个),然后把 shim exe 复制到该目录下。本文创建了 $HOME/.local/bin

布置如下:

$HOME/.local/bin
	git-receive-pack.exe # 重命名 shim exe
	git-receive-pack.shim # 新建文本文件

然而,通过命令行直接运行 git-bash -c git-receive-pack 的话,我总是无法传递参数 '/d/src/a.git',遂考虑其他方案。

发现:git receive-pack 可以实现同样效果。因此,shim 文件内容如下:

path = "powershell.exe"
args = -NoLogo -NonInteractive -NoProfile -Command git receive-pack

这里用 PowerShell 做了一次中转,是因为 cmd.exe 不会消去 '/d/src/a.git' 的单引号,从而 git 找不到仓库位置。BUG!

大功告成。

通过 Git Daemon

参考 git-scm.com/docs/git-da…

远端:

# base-path 相当于 chroot 的效果
# 默认端口 9418
git daemon --enable=receive-pack --reuseaddr --base-path="D:\src"

然后在目标仓库里创建一个空文件 .git/git-daemon-export-ok。这是 git daemon 的简易安全防护。

本地:

# 拼起来就是 "D:\src\a.git"
git remote set-url pc2 "git://hostname/a.git"

Git 官方文档吹的天花乱坠,结果试用时卡死在 Writing objects 途中,遂放弃这一用法。