All of lore.kernel.org
 help / color / mirror / Atom feed
* how to check for uncommitted/unstaged changes on remote side before pushing
@ 2015-11-08 21:23 Marc Haber
  2015-11-09  8:25 ` Dennis Kaarsemaker
  0 siblings, 1 reply; 4+ messages in thread
From: Marc Haber @ 2015-11-08 21:23 UTC (permalink / raw)
  To: git

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

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: how to check for uncommitted/unstaged changes on remote side before pushing
  2015-11-08 21:23 how to check for uncommitted/unstaged changes on remote side before pushing Marc Haber
@ 2015-11-09  8:25 ` Dennis Kaarsemaker
  2015-11-09  9:31   ` Marc Haber
  0 siblings, 1 reply; 4+ messages in thread
From: Dennis Kaarsemaker @ 2015-11-09  8:25 UTC (permalink / raw)
  To: Marc Haber, git

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

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: how to check for uncommitted/unstaged changes on remote side before pushing
  2015-11-09  8:25 ` Dennis Kaarsemaker
@ 2015-11-09  9:31   ` Marc Haber
  2015-11-09  9:38     ` Dennis Kaarsemaker
  0 siblings, 1 reply; 4+ messages in thread
From: Marc Haber @ 2015-11-09  9:31 UTC (permalink / raw)
  To: Dennis Kaarsemaker; +Cc: git

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

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: how to check for uncommitted/unstaged changes on remote side before pushing
  2015-11-09  9:31   ` Marc Haber
@ 2015-11-09  9:38     ` Dennis Kaarsemaker
  0 siblings, 0 replies; 4+ messages in thread
From: Dennis Kaarsemaker @ 2015-11-09  9:38 UTC (permalink / raw)
  To: Marc Haber, git

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

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2015-11-09  9:38 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-11-08 21:23 how to check for uncommitted/unstaged changes on remote side before pushing Marc Haber
2015-11-09  8:25 ` Dennis Kaarsemaker
2015-11-09  9:31   ` Marc Haber
2015-11-09  9:38     ` Dennis Kaarsemaker

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.