LoginSignup
20

More than 5 years have passed since last update.

Gitがv2.3.0になって、Push to Deployがしやすくなって便利

Last updated at Posted at 2015-02-18

概要

割と便利だったので勢いで書いた。

開発用に用意しているサーバー(以下remote)でcloneしてあるリポジトリに対して、「masterとかfeature branchを更新したいなー」と思って、おもむろにpushしようとすると怒られる場合があるんですよね。

remote
git status
#=> On branch master
#=> Your branch is up-to-date with 'origin/master'.
#=> nothing to commit, working directory clean
client
git push remote master
#=> (中略)
#=> To takoba@123.45.67.89:/hoge/fuga
#=>  ! [remote rejected] master -> master (branch is currently checked out)
#=> error: failed to push some refs to 'takoba@123.45.67.89:/hoge/fuga'

それが、最近リリースされたGit v2.3.0だと、receive.denyCurrentBranch = updateInsteadを設定しておけば怒られずに済むし、安全にPush to deployができるようになってて便利だよ、というエントリ。

通常の挙動

defaultでは、“(non-bareなリポジトリが)pushしたいbranchをremoteでcheckoutしている”状態だと、pushできないようになってます。
これはv2.3.0でも同様です。

client
git push remote master
#=> (中略)
#=> remote: error: refusing to update checked out branch: refs/heads/master
#=> remote: error: By default, updating the current branch in a non-bare repository
#=> remote: error: is denied, because it will make the index and work tree inconsistent
#=> remote: error: with what you pushed, and will require 'git reset --hard' to match
#=> remote: error: the work tree to HEAD.
#=> remote: error: 
#=> 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.
#=> remote: error: 
#=> remote: error: To squelch this message and still keep the default behaviour, set
#=> remote: error: 'receive.denyCurrentBranch' configuration variable to 'refuse'.
#=> To takoba@123.45.67.89:/hoge/fuga
#=>  ! [remote rejected] master -> master (branch is currently checked out)
#=> error: failed to push some refs to 'takoba@123.45.67.89:/hoge/fuga'

こんなかんじに拒否られます。
なので、ぼくは以下のような流れで“擬似的なmaster(tmp)にmasterをmerge”していました。

remote
git checkout -b tmp
#=> Switched to a new branch 'tmp'

git status
#=> On branch tmp
#=> nothing to commit, working directory clean
client
git push remote master
#=> (略)
server
 git merge master 
#=> Updating 1234567..abcdefg
#=> Fast-forward
#=>  a.php     | 16 ++++++++--------
#=>  b.html    | 20 ++++++++++++++++++++
#=>  c.js      | 28 +++++++++++++++++++++++++---
#=>  d.css     | 10 ----------
#=>  e.css     |  6 ++++++
#=>  README.md |  1 + 
#=>  5 files changed, 60 insertions(+), 21 deletions(-)
#=>  create mode 100644 e.css
#=>  delete mode 100644 d.css

“bareなリポジトリ”とは?

ちなみに、git cloneには--bareというオプションがあります。
bareなリポジトリ(bare repository)とは、簡単に言えば“GitHubのようにソースコードをホスティングするサーバーで用意するリポジトリ”です。

git clone --bare https://github.com/takoba/fuga.gitというかんじでcloneしたリポジトリは、通常のリポジトリとディレクトリ構成が異なります。
通常ソースコードが配置されている“作業ディレクトリ”を持たず、commitデータやbranchのデータなどGitリポジトリとしての情報のみを主に保持しているリポジトリとなります。

git clone --bare https://github.com/takoba/fuga.git
#=> Cloning into bare repository 'fuga'...
#=> (中略)
#=> Checking connectivity... done.

# `.git/`がrepositoryのrootにそのまま展開されてるかんじ?
ls -al ./fuga
#=> total 32
#=> drwxr-xr-x  10 takoba  takoba   340  2 16 11:41 .
#=> drwxr-xr-x+ 56 takoba  takoba  1904  2 16 11:41 ..
#=> -rw-r--r--   1 takoba  takoba    23  2 16 11:41 HEAD
#=> -rw-r--r--   1 takoba  takoba   175  2 16 11:41 config
#=> -rw-r--r--   1 takoba  takoba    73  2 16 11:41 description
#=> drwxr-xr-x  11 takoba  takoba   374  2 16 11:41 hooks
#=> drwxr-xr-x   3 takoba  takoba   102  2 16 11:41 info
#=> drwxr-xr-x   4 takoba  takoba   136  2 16 11:41 objects
#=> -rw-r--r--   1 takoba  takoba   291  2 16 11:41 packed-refs
#=> drwxr-xr-x   4 takoba  takoba   136  2 16 11:41 refs

v2.3.0でPush to deployするには

git configで、receive.denyCurrentBranchupdateInsteadに設定しておきます。

remote
git config --get receive.denyCurrentBranch
#=> (empty)

git config receive.denyCurrentBranch updateInstead
git config --get receive.denyCurrentBranch
#=> updateInstead

git status
#=> On branch master
#=> Your branch is up-to-date with 'origin/master'.
#=> nothing to commit, working directory clean
client
git push remote master 
#=> (中略)
#=> To takoba@123.45.67.89:/hoge/fuga
#=>    25da1ec..c967392  master -> master

無事pushできました。

receive.denyCurrentBranch = ignoreはこわい

v2.3.0以前でもreceive.denyCurrentBranchignoreを設定しておくとpushできたりしました。
ですが、割とリポジトリがぶっ壊れるようになるので微妙。

なので、なるべく利用しない方がよいです。
複数のclientから操作するケースではcommitが闇に葬られる可能性があるので、使わないように...

参考

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
20