git hook to create staging branch

我与影子孤独终老i 提交于 2019-12-04 21:23:05

You may use pre-push hook and run another git-push command from within it. This way you can alter a destination ref, hence push data on a staging branch and abort execution of push on a production branch. Here is the sketch of a script:

#!/bin/sh

#You may want to iterate over all refs 
#in case there are more branches that are being pushed
read local_ref local_sha remote_ref remote_sha

#Make sure you are not running the hook ad inifinitum
[[ $remote_ref =~ .*"staging".* ]] && exit 0

#Make sure these are unique
name="$(git config --get user.name | awk '{print $1;}' | tr '[:upper:]' '[:lower:]')"

#Compose a staging branch name accordingly
staging_branch="$(echo "$remote_ref" | sed 's:refs/heads/production/:staging/:')"
staging_branch="$staging_branch/$name"

git push origin master:"$staging_branch"  

#Don't forget that exit status needs to be != 0
#unless you want to push the same changes twice
exit 1

You need to consider some more complex cases, but I guess it should work after few adjustments .

Later you may run whatever tests you want on a CI server, push it to production and delete a staging branch. You probably want to configure each local repository so git-fetch prunes automatically:

 git config remote.origin.prune true

That way devs won't see outdated references to remote staging branches (if you choose to delete them).

Alternatively you could try to set master's upstream to an adequate staging branch. However it would probably get messy if you deleted a remote ref.

Bottom line

I don't think it's the most elegant solution, but I believe it answers your question directly. One of the drawbacks of this approach is the fact that ultimately it doesn't exit with 0. I don't know how it would be handled by some external tools. When you are using a command line it just generates an error line you can ignore.

You may want to consider @VonC's solution or some kind of other policy to prevent from pushing directly to a production branch.

EDIT:

A command line message would look like this:

That is a management better addressed with forks:

By forking a repo, bob can push to it without having to rename branches: master will be in bitbucket.org/bob/repo/master.

He can then make a PR (Pull Request) to the staging repo (itself a fork of the prod repo), dedicated to consolidate contributions from developers.

Once the code behaves as expecting in the staging repo, a PR can be made to the prod repo (managed only by few people)

That workflow is easier than trying to fiddle with branch names and manage everything in one remote repo, for which there is no hook (only webhook).

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!