如何推送到非裸露的Git存储库?


150

我通常通过ssh(屏幕和vim)在远程服务器上工作,那里有一个Git存储库。有时我不在线,所以我在笔记本电脑上有一个单独的存储库(从远程克隆)。

但是,由于我通常位于防火墙后面或没有公共IP,因此无法从远程存储库中提取信息。

我读过我应该只推送到裸仓库。然后,我应该如何将更改推送到远程存储库?



3
有2个远程仓库,一个裸仓库和一个普通仓库,并使用钩子。看起来似乎很麻烦,但是根据git ready官方git wiki的建议,您提交一份裸仓库。这可能就是为什么大多数git repo主机(例如GitHub,Bitbucket)都包括后接收钩子的原因,因此您可以POST到服务器上的URL,该URL运行例如执行的脚本git pull github master
杰克·伯杰

Answers:


136

receive.denyCurrentBranch updateInstead

此选项在Git 2.3中添加如果干净,它可使服务器更新其工作树。

因此,如果确保在本地拉动之前始终执行提交操作,并在服务器上保持干净的工作树(应该这样做以避免合并冲突),那么此选项是一个很好的解决方案。

用法示例:

git init server
cd server
touch a
git add .
git commit -m 0
git config --local receive.denyCurrentBranch updateInstead

cd ..
git clone server local
cd local
touch b
git add .
git commit -m 1
git push origin master:master

cd ../server
ls

输出:

a
b

是否有可能像heroku一样创建一个没有裸
仓库的推送-ANinJa

2
@ANinJa我不明白,这不就是我的例子所做的吗?
西罗Santilli郝海东冠状病六四事件法轮功

--local可选的吗?
Yukulélé

@Yukulélé --local仅影响当前目录,并--global影响所有git repos ~/.gitconfig,请参见man git-config
Ciro Santilli郝海东冠状病六四事件法轮功

1
感谢@CiroSantilli新疆改造中心六四事件法轮功读取DOC我确认它是没有必要的“(你可以说--local但是这是默认的)”之后
Yukulélé

146

最佳选择

推入非裸露的远程存储库的最干净,最少混乱和最安全的方法可能是推入代表笔记本电脑分支的远程专用分支。

让我们看一下最简单的情况,并假设每个回购中只有一个分支:master。当您从笔记本电脑推送到远程存储库时,而不是推送master-> master,而是推送master-> laptop-master(或类似名称)。这样,推送不会影响远程仓库中当前已签出的master分支。要从笔记本电脑执行此操作,该命令非常简单:

git push origin master:laptop-master

这意味着本地master分支将被推送到远程存储库中名为“ laptop-master”的分支。在您的远程仓库中,您将有一个名为“ laptop-master”的新分支,您可以在准备好之后将其合并到远程主机中。

替代选择

也可以只推送master-> master,但是一般不建议推送到非裸仓库的当前已签出分支,因为如果您不了解正在发生的事情可能会造成混淆。这是因为推送到签出的分支不会更新工作树,因此签git status入被推送到签出的分支将显示与最近推送的完全相反的差异。如果在完成推送之前工作树脏了,那将特别令人困惑,这是不建议这样做的重要原因。

如果要尝试仅按master-> master,则命令为:

git push origin

但是,当您返回到远程仓库时,您很可能想要做一个git reset --hard HEAD使工作树与推送内容同步的工作。这可能很危险,因为如果要保留的远程工作树中有任何未提交的更改,则会将其清除。在尝试之前,请确保您知道这样做的后果,或者至少首先进行备份!

编辑从Git 2.3开始,您可以使用“ push-to-deploy” git push:https : //github.com/blog/1957-git-2-3-has-been-released。但是推送到一个单独的分支然后合并通常会更好,因为它可以进行实际的合并(因此,与合并一样,未提交的更改也可以工作)。


1
按下笔记本电脑主机后,是否可以自动执行分支操作?
rdoubleui 2010年

3
@rdoubleui:您的意思是“自动合并 ”吗?如果是这样,否,就不可能自动执行合并,因为不能保证没有人工干预就可以进行合并。可能有一些冲突需要解决。
Dan Moulding 2010年

7
在以后的版本中(?),git config receive.denyCurrentBranch ignore必须在推入非裸
仓库

3
好的答案@DanMoulding,谢谢。@rdoubleui:您始终可以将以下命令行保存为bash函数:git push origin master:laptop-master && ssh user@remotemachine 'cd repos_path && git merge laptop-master'
丰富

@rdoubleui可以自动执行合并,您可以使用gitolite并将其设置(有点复杂),以使非裸露的所有内容变得肮脏,并使用pre-git触发器将其推送到gitolite(裸露的)版本上。之后,如果合并不能在非裸露状态下解决,它将拒绝您的推送,因此您知道必须先拉出,解决合并并再次推送。我尚未进行设置,但是我正在研究中,并认为它可以工作。

17

我建议您在服务器中有一个裸存储库和一个本地工作(非裸)存储库。您可以将更改从笔记本电脑推送到服务器裸仓库,然后从该裸仓库拉到服务器工作仓库。我之所以这样说是因为您可能希望在笔记本电脑上复制服务器中有许多完整/不完整的分支。

这样,您不必担心将更改推送到服务器时在服务器工作存储库上签出的分支状态。


4

另一个选择是设置反向ssh隧道,以便可以拉动而不是推动。

# start the tunnel from the natted box you wish to pull from (local)
$ ssh -R 1234:localhost:22 user@remote

# on the other box (remote)
$ git remote add other-side ssh://user@localhost:1234/the/repo
$ git pull other-side

如果您希望隧道在后台运行

$ ssh -fNnR 1234:localhost:22 user@remote

1

你可以做:

$git config --bool core.bare true

这可以在裸机或中央存储库中完成,以便它将接受从非裸机存储库推送的任何文件。如果您在非裸仓库中执行此操作,那么我们将无法将任何文件从非裸仓库推送到裸仓库。

如果您通过在PC中创建中央和非裸仓库来练习GIT,则它可能不会在某些PC中显示已推送的文件,但已将其推送。您可以通过运行检查它。

$git log 在中央仓库。

除了推送到GitHub之外,它还会在其中显示文件。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.