首页 > 解决方案 > 本地公司服务器上的 Git 服务器 + 文件

问题描述

我正在尝试使用 GIT 在我的公司文件服务器上设置远程仓库。

我想将本地文件和更改从我的本地计算机 Repo 推送到我公司文件服务器上的“远程”Repo。

我是该项目的唯一用户。

  1. 我不能使用裸仓库,因为我希望将文件推送到“远程”。
  2. 尝试 PUSH 时将本地克隆到远程生成错误

错误: git -c diff.mnemonicprefix=false -c core.quotepath=false --no-optional-locks push -v --tags origin master:master Pushing to M:/ARC/MikeS remote: error: refusing to update签出分支:refs/heads/master
远程:错误:默认情况下,在非裸存储库中更新当前分支
远程:被拒绝,因为它会使索引和工作树不一致
远程:与您推送的内容,并将需要 'git reset --hard' 来匹配
远程:工作树到 HEAD。
远程:远程:您可以将远程存储库中的“receive.denyCurrentBranch”配置变量
远程:设置为“忽略”或“警告”,以允许推送到
远程:其当前分支;但是,除非您
远程:安排更新其工作树以匹配您在某个
远程中推送的内容:其他方式。
远程:远程:要压制此消息并仍保持默认行为,请将
远程:'receive.denyCurrentBranch' 配置变量设置为'拒绝'。

致 M:/ARC/MikeS ![远程拒绝] master -> master(当前已签出分支)错误:未能将一些参考推送到“M:/ARC/MikeS”

完成错误,见上文。

我尝试在远程仓库上使用“git config receive.denyCurrentBranch ignore”。错误已清除,但远程 Repo 上的文件。没有得到更新。

有什么解决办法吗?我知道这听起来很简单,但我就是无法让它发挥作用。

谢谢你,迈克

标签: git

解决方案


使用裸存储库(通过 SSH)是一个很好的解决方案,前提是您有正确的 pre/post-receive 挂钩,它将在非裸存储库中签出您的文件。

  • pre-receive 钩子检查您的远程存储库是否没有完成任何更改/新提交(在这种情况下,您将首先从中提取,在本地合并,然后推送到裸存储库)
  • post-receive hook:签出您推送到非裸存储库的内容,使文件可见。

含义:在您的远程服务器上,您创建两个存储库:

  • 一个非裸机(用于直接在服务器上工作)
  • 一个裸机(从本地机器推送)

那是:

ssh remoteUser@remoteServer
git init newRepo
cd newRepo
git init --bare bare

然后在本地机器上,克隆空的新(非裸存储库),修改推送 URL 以引用裸存储库 ( newRepo/bare)

git clone remoteUser@remoteServer:~/newRepo
cd newRepo
git config --add remote.origin.pushurl remoteUser@remoteServer:~/newRepo/bare

在远程服务器上,在 ~/newRepo/bare/hooks 中,添加一个 pre-receive 钩子:

#!/bin/bash

DIR="$( cd "$( dirname "$(readlink "${BASH_SOURCE[0]}")" )" && pwd )"

git fetch

# Read stdin for ref information
while read -r oldref newref refname; do

  case "${refname}" in
  */master) branch="master"
  ;;
  refs/tags/*)
    ok "Pushing tag: proceed"
    exit 0
  ;;
  *) echo "invalid branch '${refname}'"
  exit 1
  ;;
  esac

  if [[ "${newref}" == "0000000000000000000000000000000000000000" ]]; then
    ok "Deletion of oldref '${oldref}': pre-receive proceed"
    exit 0
  fi

  localsha1=${newref}

  if [[ "master" == "${branch}" ]]; then
    originsha1=$(git rev-parse origin/master)

    force="false"
    # shellcheck disable=SC2086
    if [[ "$(git rev-list ${oldref} ^${newref})" != "" ]]; then force="true"; fi

    cmd="git merge-base --is-ancestor ${originsha1} ${localsha1}"
    if ! eval "${cmd}"; then
      if [[ "${force}" == true ]]; then
        info "force push master"
      else
        fatal "Git push of '${refname}' refused because repo locally ($(hostname)) modified\nDo a git pull first" 1
        exit 1
      fi
    fi
    if git rev-parse --quiet --verify from_prod >/dev/null && ! git merge-base --is-ancestor from_prod "${localsha1}"; then
      error "Git push of '${refname}' refused because from_prod is not an ancestor"
      error "Meaning: prod has evolved, fetch and rebase on top of from_prod first, then push again"
      exit 1
    fi
    ok "Push to master will proceed"
  fi
done

和一个接收后挂钩:

#!/bin/bash
DIR="$( cd "$( dirname "$(readlink "${BASH_SOURCE[0]}")" )" && pwd )"

while read -r oldrev newrev refname
do
  case "${refname}" in
  */master) branch="master"
  ;;
  refs/tags/*)
    ok "Pushing tag: proceed post-receive"
    exit 0
  ;;
  *) fatal "invalid branch '${refname}' in post-receive (oldrev:'${oldrev}')" 1
  ;;
  esac

  if [[ "${newrev}" == "0000000000000000000000000000000000000000" ]]; then
    ok "Deletion of oldrev '${oldrev}': post-receive proceed"
    unset GIT_DIR
    cd ..
    git --work-tree=. --git-dir=.git fetch --prune
    if [ "${branch}" != "" ]; then git --work-tree=. --git-dir=.git branch -d "${branch}"; fi
    cd ./bare || fatal "Unable to go into bare of '$(pwd)'" 8
    git --git-dir=. fetch --prune
    exit 0
  fi

  info "post-receive for branch '${branch}'"
  if [ "master" == "$branch" ]; then
    info "pull from non-bare repo"
    unset GIT_DIR
    cd ..
    git --work-tree=. --git-dir=.git fetch
    git --work-tree=. --git-dir=.git fetch --tags
    if ! git --work-tree=. --git-dir=.git merge-base --is-ancestor master origin/master; then
      info "Reset non-bare master to bare master (forced update)"
      git  --work-tree=. --git-dir=.git reset --hard origin/master
    else
      info "Update non-bare master with merge from origin/master"
      git --work-tree=. --git-dir=.git pull --no-rebase origin master
    fi
  fi
done

这样,您可以直接在服务器上工作,在您的常规 ~/newRepo 非裸仓库中进行提交。
但是你也可以在你的机器上工作,并且推送而不用担心覆盖服务器上同时进行的远程提交:预接收挂钩会阻止推送。

笔记:

  • 用简单的“ ”替换脚本中的“ ok”、“ info”和“ ”)。fatalecho
  • 添加bare/您的.gitignore, 以便您的常规存储库忽略其嵌套的裸存储库。

推荐阅读