开发者

Cannot git clone a folder on a server and then edit and git push?

I used Mercurial (Hg) before, and it was ok to do something like at the local PC:

hg clone ssh://peter@hostingcompany.com/~/mysite.com

and then will have a local folder called mysite.com, and I can edit its content, commit, and say hg push and push it to the server. Of course, to have the content show up in the "working directory", I will have to ssh there and do an hg up.

With Git, if I do the same, at the serv开发者_如何学Cer, do a

git init
git add .
git commit -m "ok"

and at the local PC, do a

git clone ssh://peter@hostingcompany.com/~/mysite.com

but when I edit a file and git push ssh://peter@foo.com/~/mysite.com master, then it will refuse it, because it is not a "bare repository".

Is there a way to

  1. Push it anyway, like Hg?
  2. Or, better yet, push it and have it automatically do something like hg up -- is it git checkout, so that the content is immediately visual on mysite.com (using any web browser anywhere).

Update:

It seems that the usual practice is to push to a bare repo... but can we not use a bare repo and make (2) above work? If it is a practical way, then we don't have to stick to the "push to bare repo" rule?

If there are other reason still to push to a bare repo and clone on the server... then:

if the server had directories such as ~/mysite.com and ~/other_folder etc, then where should the repo for mysite.com sit? mysite.com is the content of the website, so if I put an index.html, then any browser in the world can see it. So is it good to create a bare repo, let ~/mysite.com clone from it, and on the local PC, use git push <path> master; ssh <path> "cd to that folder and do git checkout to update the content" automatically by 1 line on the local PC? Will the line be git push ssh://peter@hostingcompany.com/~/mysite.com master; ssh ssh://peter@hostingcompany.com/~/mysite.com 'git pull; git checkout' ?


I don't know why people are saying it's not supported. While pushing to a bare repo is the recommended practice, you can push to a non-bare by setting the receive.denyCurrentBranch config variable to 'ignore' or 'warn' as shown by the error message you get (at least on 1.7.1) when you try to do it:

remote: error: You can set 'receive.denyCurrentBranch' configuration variable to
remote: error: 'ignore' or 'warn' in the remote repository to allow pushing into
remote: error: its current branch; however, this is not recommended unless you
remote: error: arranged to update its work tree to match what you pushed in some
remote: error: other way.

I would say your workflow where you deploy with a git push followed by a hard reset on the remote side is precisely the exception to the rule for which this config variable was created.

Also, I haven't tried it personally, but the "current branch" language implies you can push to a remote branch that isn't checked out with no errors at all, after which you could do a fast-forward merge on the remote end into your checked out branch.


In Git it is usually a good practice to have the repo on the server to which other people push to be a bare repository. It is highly recommended.

git init . --bare

Here it is failing because you are pushing to a non-bare ( with a working copy ) repo and to the branch that is checked out.


In Git, you are only supposed to push to a bare repository. The best solution is to create a bare repository on the server that you push to, and then a non-bare clone of it which contains the checkout, so after you push to the bare repo, you SSH to the server and do git pull from the non-bare repo (or set up a hook to do so automatically after the bare repo receives the new version).


Git does not support pushing to a branch, that is checked out at the remote end.

The recommended way is to use bare repository on the server. Normally you either push to the repository (and make it bare) or work on it, but not both. Even if you want to have a working copy on the server, I'd suggest you look at this question.

So you have two options:

  1. Make a bare repository (mysite.com.git) and a non-bare repository (mysite.com). In the bare repository, add a post-update hook to git --git-dir=.../mysite.com pull
  2. Make just one repository and:

    1. Detach the head: git checkout master@{0}

    2. Add a post-update hook to git merge master

    The reason here is that git refuses to modify the checked-out branch, but if you uncheckout the branch, you will be able to push. And you will be able to update the working directory from a hook (hook is a script placed in hooks directory in the repository). You can either create a separate branch and check out that, or you can use the "detached HEAD" state (as suggested above—git remembers which branch is checked out by having a special reference "HEAD" that points to the branch, but if you check out something, that is not a branch, it is made to point to a revision directly and that's called a "detached branch" and since no branch is checked out, allows you to push to any of them).


You should only push to bare repositories (a bare repository has no working copy).

You have two solutions:

  • pull from your remote repository (then it will ask for solving conflicts)
  • make your remote repository a bare one

EDIT my guess that the remote repo has local modifications is wrong; don't know why you can't push, but the rest of my post is still valid: you shouldn't push to normal repos.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜