Re: how to check for uncommitted/unstaged changes on remote side before pushing

2015-11-09 Thread Dennis Kaarsemaker
On zo, 2015-11-08 at 22:23 +0100, Marc Haber wrote:
> Hi,
> 
> I am trying to abuse git as a code distribution channel and would
> like
> to be able to trigger redistribution just by git push.

[insert obligatory remark about git not being a deployment tool]

> The idea is to push to a remote to the branch that is currently
> checked out followed by a git reset --hard in the post-receive hook.
> I
> have already figured out that I need to set receive.denyCurrentBranch
> to ignore to be able to push to the currently checked out branch.

You'll need a new enough git, so you can set it to updateInstead (and
maybe use a push-to-checkout hook).

> I am also aware that it is a good idea to git pull before git push
> just in case there were local commits on the remote.

No, hooks should never pull, merge or do anything that could be
interactive.

> git reset --hard will unconditionally throw away local uncommitted
> changes. I would like to detect this situation on the remote and
> abort
> the receive progress. But my pre-receive hook does not work as
> intended. Here is my code:
>
> [snip code]
>
> What is going wrong here?

You mention a post-receive hook first, but have written a pre-receive
hook. Not sure if that's what you intended (or even if that's what's
going wrong).

> If my entire approach is wrong, what is the recommended way to 
> prevent a repository with unstaged or uncommitted changes from being 
> pushed to?

Push-to-checkout is a very simplistic way of deploying and while it
works in simple cases, I'd not recommend it. 

Two safer/saner approaches are:
- Have a separate non-bare repo, and make the post-receive hook in a
  bare repo trigger a fetch+reset in the non-bare one
- Use git archive and symlink trickery for even better deploys

Questions like this come up in #git all the time, so I wrote up a few
more detailed recipes here, including working hooks and config for all
three ways of deploying: 
http://git.seveas.net/simple-deployments-with-git.html

-- 
Dennis Kaarsemaker
www.kaarsemaker.net


--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: how to check for uncommitted/unstaged changes on remote side before pushing

2015-11-09 Thread Marc Haber
Hi Dennis,

thanks for your comments. I appreciate that.

On Mon, Nov 09, 2015 at 09:25:00AM +0100, Dennis Kaarsemaker wrote:
> On zo, 2015-11-08 at 22:23 +0100, Marc Haber wrote:
> > Hi,
> > 
> > I am trying to abuse git as a code distribution channel and would
> > like
> > to be able to trigger redistribution just by git push.
> 
> [insert obligatory remark about git not being a deployment tool]

That's why I said "abuse" ;-)

Abusing git here has the advantage that one can save local changes and
merge them, which is handy for the task at hand (which is deploying my
dotfiles to "my" servers).

> > The idea is to push to a remote to the branch that is currently
> > checked out followed by a git reset --hard in the post-receive hook.
> > I
> > have already figured out that I need to set receive.denyCurrentBranch
> > to ignore to be able to push to the currently checked out branch.
> 
> You'll need a new enough git, so you can set it to updateInstead (and
> maybe use a push-to-checkout hook).

That's a nice new feature. Unfortunately even the git 2.1.4 which is
in current Debian stable does not support that yet, but I think I can
live with a backport, and in the past git has shown to be reasonably
easy to backport.

> > I am also aware that it is a good idea to git pull before git push
> > just in case there were local commits on the remote.
> 
> No, hooks should never pull, merge or do anything that could be
> interactive.

I mean that I would manually pull on the master before pushing to the
remote, thus making sure that the push will go through fine. With the
pull, I would get all committed remote changes merged locally on the
master, leaving uncommitted and unstaged changes to worry about.

> > git reset --hard will unconditionally throw away local uncommitted
> > changes. I would like to detect this situation on the remote and
> > abort
> > the receive progress. But my pre-receive hook does not work as
> > intended. Here is my code:
> >
> > [snip code]
> >
> > What is going wrong here?
> 
> You mention a post-receive hook first, but have written a pre-receive
> hook. Not sure if that's what you intended (or even if that's what's
> going wrong).

My intention was having a pre-receive hook check for uncommitted or
unstaged changes and abort the process if there were any. If there
were none, the push would go through and a post-receive hook would
update the working copy.

With updateInstead, I could probably go without the post-receive hook,
but in my understanding, the check for uncommitted/unstaged changes
would still be handy and helpful.

> > If my entire approach is wrong, what is the recommended way to 
> > prevent a repository with unstaged or uncommitted changes from being 
> > pushed to?
> 
> Push-to-checkout is a very simplistic way of deploying and while it
> works in simple cases, I'd not recommend it.
> 
> Two safer/saner approaches are:
> - Have a separate non-bare repo, and make the post-receive hook in a
>   bare repo trigger a fetch+reset in the non-bare one
> - Use git archive and symlink trickery for even better deploys

Both these approaches would make it harder or even impossible to merge
local changes done on the remotes.

> Questions like this come up in #git all the time, so I wrote up a few
> more detailed recipes here, including working hooks and config for all
> three ways of deploying: 
> http://git.seveas.net/simple-deployments-with-git.html

Thanks, that is appreciated. I refrained from coming to #git since my
experience is that complex issues are hard to manage on IRC. I have,
however just joined as Zugschlus, so if you want to talk to me
directly feel free to do so.

Greetings
Marc

-- 
-
Marc Haber | "I don't trust Computers. They | Mailadresse im Header
Leimen, Germany|  lose things."Winona Ryder | Fon: *49 6224 1600402
Nordisch by Nature |  How to make an American Quilt | Fax: *49 6224 1600421
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: how to check for uncommitted/unstaged changes on remote side before pushing

2015-11-09 Thread Dennis Kaarsemaker
On ma, 2015-11-09 at 10:31 +0100, Marc Haber wrote:
> Abusing git here has the advantage that one can save local changes 
> and merge them, which is handy for the task at hand (which is 
> deploying my dotfiles to "my" servers).

For this I really like vcsh (https://github.com/RichiH/vcsh/) in
combination with a .bashrc.d snippet that updates dotfiles upon login
when possible (
https://github.com/seveas/dotfiles/blob/master/.bashrc.d/vcsh.sh)


-- 
Dennis Kaarsemaker
www.kaarsemaker.net


--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


how to check for uncommitted/unstaged changes on remote side before pushing

2015-11-08 Thread Marc Haber
Hi,

I am trying to abuse git as a code distribution channel and would like
to be able to trigger redistribution just by git push.

The idea is to push to a remote to the branch that is currently
checked out followed by a git reset --hard in the post-receive hook. I
have already figured out that I need to set receive.denyCurrentBranch
to ignore to be able to push to the currently checked out branch.

I am also aware that it is a good idea to git pull before git push
just in case there were local commits on the remote.

git reset --hard will unconditionally throw away local uncommitted
changes. I would like to detect this situation on the remote and abort
the receive progress. But my pre-receive hook does not work as
intended. Here is my code:

#!/bin/bash

echo "this is the pre-receive hook on $HOSTNAME"

if [ "$(git status --porcelain | wc -l)" -ne 0 ]; then
  echo "there are uncommitted changes"
  echo "PWD=$PWD"
  echo "git status --porcelain"
  git status --porcelain
  echo "end git status"
  exit 1
fi

When I invoke my hook from the remote, everything is fine:

mh@jessie:~/.stdacct$ .git/hooks/pre-receive
this is the pre-receive hook on jessie
there are uncommitted changes
PWD=/home/mh/.stdacct
git status --porcelain
 M dotfiles/.bashrc
 M hooks/pre-receive-hook
?? hooks/pre-receive-hook~
end git status
mh@jessie:~/.stdacct$ 

However, the output is different when invoked during a push:

[7/504]mh@swivel:~/git/stdacct$ git push jessie
Counting objects: 4, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (4/4), done.
Writing objects: 100% (4/4), 363 bytes | 0 bytes/s, done.
Total 4 (delta 3), reused 0 (delta 0)
remote: this is the pre-receive hook on jessie
remote: there are uncommitted changes
remote: PWD=/home/mh/.stdacct/.git
remote: git status --porcelain
remote: ?? HEAD
remote: ?? ORIG_HEAD
remote: ?? config
remote: ?? description
remote: ?? hooks/applypatch-msg.sample
remote: ?? hooks/commit-msg.sample
remote: ?? hooks/post-receive
remote: ?? hooks/post-update.sample
remote: ?? hooks/pre-applypatch.sample
remote: ?? hooks/pre-commit.sample
remote: ?? hooks/pre-push.sample
remote: ?? hooks/pre-rebase.sample
remote: ?? hooks/pre-receive
remote: ?? hooks/prepare-commit-msg.sample
remote: ?? hooks/update.sample
remote: ?? index
remote: ?? index.lock
remote: ?? info/
remote: ?? logs/
remote: ?? objects/
remote: ?? refs/
remote: end git status
To ssh://jessie/home/mh/.stdacct
 ! [remote rejected] jessie -> jessie (pre-receive hook declined)
error: failed to push some refs to 'ssh://jessie/home/mh/.stdacct'

It looks like the hook thinks that it is invoked inside the .git/hooks
directory which is not considered part of the repository.

What is going wrong here?

If my entire approach is wrong, what is the recommended way to prevent
a repository with unstaged or uncommitted changes from being pushed to?

Greetings
Marc


-- 
-
Marc Haber | "I don't trust Computers. They | Mailadresse im Header
Leimen, Germany|  lose things."Winona Ryder | Fon: *49 6224 1600402
Nordisch by Nature |  How to make an American Quilt | Fax: *49 6224 1600421
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html