Help us understand the problem. What is going on with this article?

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

More than 5 years have passed since last update.

概要

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

開発用に用意しているサーバー(以下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が闇に葬られる可能性があるので、使わないように...

参考

takoba
インターネットと音楽とカレーライスを主にたべます
https://twitter.com/takoba_
connehito
「人の生活になくてはならないものをつくる」というミッションの元、ママリを開発・運営する会社です。
https://connehito.com
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした