如何在 Git 提交后自动推送?

102

如何设置Git自动将本地库的每个提交(包括自动提供我的passphrase)推送到远程仓库?


2
你正在使用哪种协议?如果它提示输入密码,我假设这是SSH或HTTP。 - Mark Longair
1
此外,在处理 Git 相关问题时,至少提及您使用的操作系统通常会很有帮助。 - Mark Longair
2
我对这样的设置是否明智存疑。这将消除任何将您的更改重新组织为不同提交集(特别是变基)的能力。对于像我这样经常犯错误的人来说,这样的设置最终无法对我有所帮助。 - jpmc26
8个回答

165

首先,确保您可以在不提供密码的情况下手动推送。 如果您正在通过HTTP或HTTPS进行推送,则需要创建一个包含登录详细信息的.netrc文件或者在远程URL中添加用户名和密码。如果使用SSH,您可以创建私钥没有密码的密钥对,或者使用ssh-agent缓存私钥。

接下来,您应该在 .git/hooks/post-commit 创建一个可执行文件(chmod +x),其中包含以下内容:

#!/bin/sh
git push origin master

如果你想推送到除了origin以外的远程仓库,或者推送除了master分支以外的分支,那么你需要自定义该行。请确保该文件是可执行的。


4
无法让ssh-agent记住我的密码,所以不得不将其设为空。希望我的妻子不会攻击我的账户 :) - ulu
说到自定义,如果我只想以这种方式推送一些而不是所有分支怎么办?例如,我只想自动推送那些在.git/config中带有前缀feature/xy/的相应远程分支的分支。 - Asclepius
8
将所有本地分支推送到远程"origin"仓库中。 - Yada
7
将chmod +x .git/hooks/post-commit翻译成中文即可:赋予.git/hooks/post-commit文件执行权限。 - webcpu
如果您不想存储密码,那么这种方法也非常有效。唯一的问题是每次提交后您都必须输入密码。 - Gagan

40
如果你开始使用除主分支之外的其他分支,你可能希望自动推送当前分支。我的钩子(.git/hooks/post-commit)看起来像这样:
#!/usr/bin/env bash

branch_name=$(git symbolic-ref --short HEAD)
retcode=$?
non_push_suffix="_local"

# Only push if branch_name was found (my be empty if in detached head state)
if [ $retcode -eq 0 ] ; then
    #Only push if branch_name does not end with the non-push suffix
    if [[ $branch_name != *$non_push_suffix ]] ; then
        echo
        echo "**** Pushing current branch $branch_name to origin [i4h post-commit hook]"
        echo
        git push origin $branch_name;
    fi
fi

它会推送当前分支,如果能够使用git symbolic-ref确定分支名称。
"如何在Git中获取当前分支名称?"解决了这个问题以及其他获取当前分支名称的方法。
当在任务分支中工作并期望进行一些制作香肠时(推送后很难进行变基),每个分支的自动推送可能会干扰。因此,钩子不会推送以定义后缀结尾的分支(例如"_local")。

对于第一行,我必须使用 #!/bin/sh 才能让它正常工作。否则它一直显示:error: cannot run .git/hooks/post-commit: No such file or directory。谢谢,我最喜欢你的解决方案。 - oyalhi
感谢您的评论,@oyalhi,我已经更新了答案中的shebang行。现在应该更好地移植了! - i4h
你好,我遇到了这个错误:.git/hooks/post-commit: 第3行:查找匹配''时意外的EOF .git/hooks/post-commit: 第17行:语法错误:意外的文件结尾 - otto
嘿,确实有一个丢失的反引号。我已经更新了答案,请再试一次。 - i4h
为什么要使用 #!/usr/bin/env bash?它的含义是什么(它应该做什么)?这是为了使用 Bash 而不是 Dash (sh) 吗?在哪个系统上?Ubuntu 16.04 (Xenial Xerus)?为什么它与默认的 #!/usr/sh 不同? - Peter Mortensen

14
.git/hooks目录下创建名为“post-commit”的文件,其中包含“git push”的内容。如果您想自动提供密码,需要进行修改。

什么样的修改?也许可以扩展回答(和/或指向一些参考资料或Stack Overflow帖子)? - Peter Mortensen
此外,post-commit 文件需要可执行。 - Endle_Zhenbo

3

不需要 ssh-agent,只需使用另一个无密码的 git 专用 ssh 密钥:ssh-keygen -t ed25519 -f ~/.ssh/id_pushonlyecho $'\nHost pushonly\nHostname DESTINATION\nIdentityFile ~/.ssh/id_pushonly\n' >> ~/.ssh/config。在 DESTINATION 上使用来自 ~/.ssh/id_pushonly.pub 的公钥配置 git-shell,如 https://superuser.com/a/444899/72223 所示。所需的 git URL 类似于 git@pushonly:path/to/repo.git。调试:ssh git@pushonly COMMAND 必须在 DESTINATION 上运行 git-shell -c COMMAND。有关 COMMAND 请参阅 man git-shell - Tino
@Tino 谢谢。你为什么使用数字签名方案 -t ed25519?我通常使用 -t rsa,尽管最近我不得不在 ssh-keygen 中添加 -m PEM(https://dev59.com/dVQJ5IYBdhLWcg3wiWec#53645530,https://dev59.com/9bDla4cB1Zd3GeqP7mQC#53729009)。 - VonC
@Tino 我知道 RSA 更慢,如果长度低于 2048 位则不够安全(https://bagja.net/blog/upgrade-ssh-key-to-ed25519.html),但是我在工作中需要处理旧的 OpenSSH 服务器,这些服务器可能无法正确解释 ed255519 签名。 - VonC
我主要使用ed25519,因为它可以在~/.ssh/authorized_keys中提供简短而方便的行。此外,非常有趣的是DJB关于ed255519的写作:安全防范旁路攻击(Spectre),CPU占用率低等等。顺便说一下,当处理旧的sshd时,我通常会为它们创建一个特殊的密钥,然后在~/.ssh/config中进行配置。 - Tino

1

这是一个用于Git自动push到远程仓库的Bash脚本:

  1. 自动检查ssh-agent
  2. 使用expect脚本自动发送密码
  3. 使用方法很简单:先cd /path/to/your/repository,然后执行push

将此脚本添加到文件中,例如$HOME/.ssh/push

#!/bin/bash

# Check connection
ssh-add -l &>/dev/null
[[ "$?" == 2 ]] && eval `ssh-agent` > /dev/null

# Check if Git config is configured
if [ ! $(git config user.name) ]
then
    git config --global user.name <user_name>
    git config --global user.email <user_email>
fi

# Check if expect is installed
if [[ ! $(dpkg -l | grep expect) ]]
then
    apt-get update > /dev/null
    apt-get install --assume-yes --no-install-recommends apt-utils expect > /dev/null
fi

# Check identity
ssh-add -l &>/dev/null
[[ "$?" == 1 ]] && expect $HOME/.ssh/agent > /dev/null

# Clean and push the repository
REMOTE=$(git remote get-url origin)
URL=git@github.com:${REMOTE##*github.com/}
[[ $REMOTE == "http"* ]] && git remote set-url origin $URL
git add . && git commit -m "test automatically push to a remote repo"
git status && git push origin $(git rev-parse --abbrev-ref HEAD) --force


将其链接到 /bin 目录,这样只需使用 push 命令即可调用它:
sudo ln -s $HOME/.ssh/push /bin/push
chmod +x /bin/push

0

以下是针对使用Linux和Windows(Git Bash)的人们,无需提供SSH密钥的简单推送/拉取指令。

在您的客户端上:

  1. 检查是否已生成SSH密钥:

     $ ls ~/.ssh/id_rsa.pub; ls ~/.ssh/id_dsa.pub
     /c/Users/Cermo/.ssh/id_rsa.pub  <-- 我有RSA密钥
     ls: cannot access '/c/Users/Cermo/.ssh/id_dsa.pub': No such file or directory
    
  2. 如果没有任何密钥(两个“ls:cannot access ...”行),请生成一个新密钥。如果您已经拥有其中任何一个密钥,则跳过此步骤。

    $ ssh-keygen.exe
    Generating public/private rsa key pair.
    Enter file in which to save the key (/c/Users/Cermo/.ssh/id_rsa):
    Enter passphrase (empty for no passphrase): <-- 按回车键
    Enter same passphrase again: <-- 按回车键
    
  3. 将您的密钥复制到您想要使用git拉取或推送的远程服务器:

    $ ssh-copy-id user_name@server_name
    /usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to
    filter out any that are already installed
    /usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you
    are prompted now it is to install the new keys
    user_name@server_name's password:
    
    Number of key(s) added: 1
    
    Now try logging into the machine, with:   "ssh 'user_name@server_name'"
    and check to make sure that only the key(s) you wanted were added.
    

注意:在此操作期间,您需要提供一个密码。之后,您的拉/推操作将不会要求密码。

注意2:在使用此过程之前,您必须至少使用user_name登录到服务器一次(SSH密钥所复制的主目录在第一次登录时创建)。


0
  1. 创建一个Git文件:commit.sh

    #!/bin/sh
    cd c:/Users/Lenovo/Desktop/nalms/src
    git add --all
    timestamp() {
      date +"at %H:%M:%S on %d/%m/%Y"
    }
    git commit -am "定期自动提交 $(timestamp)"
    git push origin master
    
  2. 打开窗口任务计划程序

  3. 创建新任务

  4. 常规 → 命名任务

  5. 进入触发器部分并启用任务计划程序

  6. 按下 完成 按钮


什么是“窗口任务计划程序”?这是在 Windows 上吗?您是否指的是Windows任务计划程序?或者其他什么东西?您还可以提供截图来补充说明(甚至是手绘圆圈(不开玩笑))。请通过编辑(更改)您的答案来回复,而不是在评论中回复(* * *不要包含“编辑:”,“更新:”或类似内容-答案应该像今天写的一样)。 - Peter Mortensen

0

如果您正在使用Husky,则默认情况下将覆盖post-commit挂钩文件。

我们在package.json中使用此命令将任何提交自动合并到主分支并推送。 (首先运行yarn add --dev git-branch-is。)

  "husky": {
    "hooks": {
     "post-commit": "git-branch-is master && git rebase origin master && git push origin master"`
    }
  }

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