问题
I need to git push to remote, and that push need to be current working copy. Because, pushed source is a web host. So, pushed files need to be currently in use. I am sure no one will edit files at the host :)
This question is follow up of these 2 questions, Is it possible to have a git repo inside another git repo and what difference does --bare switch make when initing a git repo?
Edit: bare repo is not what I want, since files need to be directly used on remote machine, and need to be found on the locations where I put them.
Edit2: It is my understanding that bare repo doesn't keep the file hieararchy, and keep repo data in root directory
回答1:
Here is a step-by-step on how to create a git repo on your web host that will allow direct pushes, set it up as a remote for your local repo, and push changes to it. Note that you need to have ssh access to your web host, and have git installed.
On your web host (ssh'd in):
# create an empty repo on your web host; note its path
mkdir site
cd site
git init
# configure it to allow pushes to the current checked-out branch
# without complaining (direct push)
git config receive.denyCurrentBranch ignore
Now with your local repo (run these git commands inside the repo):
# create the reference to the web host remote for pushing
# /path/to/the/repo is the path to the repo you made above on the web host:
# it will be an absolute path OR relative to your ssh chroot (depends on the host)
git remote add deploy ssh://your_user@your_host/path/to/the/repo
# finally, push your changes!
git push deploy master
Now, your changes have been pushed to the checked-out repo on the web host. However, they will not be reflected in the working dir (that is, your changes will not take effect immediately). This is because you have pushed directly to the active branch. To finish up, you need to either
- manually perform a
git checkout -f
to update the working dir - make a
git post-receive
hook to do it automatically.
To have instant, automatic deployment with a post-receive
hook check out this git site deployment howto.
回答2:
This question is really old, but I found a much better solution (for my situation at least) than the solutions listed here.
From the manual for git config
, as of Git 2.3.0:
Another option is "updateInstead" which will update the working directory (must be clean) if pushing into the current branch. This option is intended for synchronizing working directories when one side is not easily accessible via interactive ssh (e.g. a live web site, hence the requirement that the working directory be clean).
So git config receive.denyCurrentBranch updateInstead
(on the receiving repository) worked perfectly for me. It allows me to push and updates the working directory of the receiving repository automagically (as long as that working directory is clean when the push happens).
回答3:
While this is rather old it is extremely discouraged to push to a working tree. https://git.wiki.kernel.org/index.php/GitFaq#Unexpected_behavior
A better method would be to create a bare repo mirroring the website's working tree.
All a bare repo is, is a repository with no working tree or rather with no files checked out. The hierarchy exists all things considered and can be checked out. In otherwords, it acts as a host for changes only.
Without knowing the directory hierarchy you are working with for your web, I am going to assume it is a standard website layout using chrooted home EG: /home/user/www
On the server using ssh with git installed:
Create a working tree of the current site
cd /home/user/public_html
git init
git add .
git commit -m "Initial Commit"
Create a bare repository to remote push to from your local system
mkdir /home/user/deploy.git
cd /home/user/deploy.git
git init --bare
Link your working tree repository and your bare deploy repository
cd /home/user/public_html
git remote add deploy /home/user/deploy.git
git remote show deploy
* remote deploy
URL: /home/user/deploy.git
git push deploy master
Now set up a new repo on your local system
git clone ssh://user@example.com/home/user/deploy.git
git branch -a
*master
remotes/origin/HEAD
remotes/origin/master
Now we setup 2 hooks to instantly make changes to your web remote repo when you push to it or if someone else you give access to pushes to it. Since git config receive.denyCurrentBranch ignore will lead to trouble in the long run
On the remote server enable post-update for deploy
cd /home/user/deploy.git/hooks
mv post-update.sample post-update
vi post-update
Change your post-update hook to the below and save
#!/bin/sh
echo "Pulling changes into public_html [deploy post-update]"
cd /home/user/public_html || exit
unset GIT_DIR
git pull deploy master
exec git update-server-info
Now we set up your web working tree to push its changes to deploy if something is committed to it.
cd /home/user/public_html/.git/hooks
mv post-commit.sample post-commit
vi post-commit
Then change post-commit hook to the following
#!/bin/sh
echo "Pushing changes to deploy [public_html post-commit]"
git push deploy
You still have the option to checkout your web working tree if you need to. This will let you pull your changes from deploy to your web's working tree when you push your local system's master. You can branch, rebase, revert, etc without affecting your web's working tree, without worrying about conflict markers, by instead just using the bare deploy repository. If you need more control over what's committed you can use post-receive instead of or in conjunction with post-update.
Hope this helps someone else looking to do the same as the OP.
来源:https://stackoverflow.com/questions/7152607/git-force-push-current-working-directory