Git HTTPSable Push 作った

TL;DR

remote url が git://...でもgit@...でもhttps://...でも、GITHUB_ACCESS_TOKEN以外設定不要で、https push出来る git_httpsable-push 作った。

git httpsable-push origin CURRENT_BRNANCH

こんな感じに使う。使い道と使い方はこっちに書いた。

Httpsで簡単に、ログ安全に、git pushする Git HTTPSable Push – Saddler – checkstyle to anywhere

github enterpriseだろうとbitbucketだろうとgitlabだろうと使えるように、内部的にはいろいろ環境変数で上書けるようにしてある。が、それで必要十分かは未検証。

背景

少なめの設定で、デフォルト安全に倒した操作を行えるようにしておきたい。

git push --quiet "https://${GITHUB_ACCESS_TOKEN}@github.com/.git" gh-pages 2> /dev/null

これで--quietや2> /dev/null 忘れたりtypoするとGitHub token漏れるのひどいと思う。GitHubのtokenの無駄な権限のデカさが根源だけど、あれ細分化したらそれはそれでコントロール不能になるだろうから、悩ましい。

gh-pages使うときにpushしたいならGit HTTPSable Push便利。ただ、gh-pages使うなら「default branchをgh-pagesにして、生jekyllをGitHub任せの運用」にしない理由がよくわからない。いろいろ事情があるのか。

参照

広告

ssh protocol形式のgit のurlをparse/buildするuri-ssh_git書いた

ssh protocol形式のgit のurlをparse/buildするuri-ssh_git書いた。

経緯

GitHubのclone url表現には3つある。

それぞれ、git protocol, ssh protocol, https protocolだ。gitとhttpsはいいんだけど、ssh形式は、これはurl的には

ssh://git@github.com:22/kyanny/hello.git

Git における SSH オプション指定方法あれこれ – Qiita

だそうだ。で、ssh形式をparseするのにURI.parse や Addressable.parse でparseできてた、つもりだったんだけど、これはいままでAddressableでpathだけ使ってたからであって、これがたまたまparseしてただけっぽい。

# URI
url = URI.parse('git@github.com:schacon/ticgit.git')
URI::InvalidURIError: bad URI(is not URI?): git@github.com:schacon/ticgit.git

# Addressable
url = Addressable::URI.parse('git@github.com:schacon/ticgit.git')
#=> #<Addressable::URI:0x3fedf48fb430 URI:git@github.com:schacon/ticgit.git>
url.path #=> "schacon/ticgit.git"
url.scheme #=> "git@github.com"

で、ssh形式のurlどうパースするんだ…ってググったりnet-ssh見たりしたけど、見つからなくて取り急ぎgem書いた。Addressableのuri.schemeを分割するのは無し。偶然parseできてるだけな気がするので。@と:でぱっと見区切れるようにみえるんだけど、portとか相対パス絶対パスとかどうなるんだ、っていうので検索、検索。なお最終的にはぱっと区切って終わりにした。

Usage

url = URI::SshGit.parse('git@github.com:packsaddle/ruby-uri-ssh_git.git')
# #<URI::SshGit::Generic git@github.com:packsaddle/ruby-uri-ssh_git.git>

# http://docs.ruby-lang.org/ja/2.2.0/class/URI=3a=3aGeneric.html
# :scheme ,:userinfo, :host, :port, :registry, :path, :opaque, :query, :fragment
url.scheme #=> nil
url.userinfo #=> 'git'
url.user #=> 'git'
url.password #=> nil
url.host #=> 'github.com'
url.port #=> nil
url.registry #=> nil
url.path #=> '/packsaddle/ruby-uri-ssh_git.git'
url.opaque #=> nil
url.query #=> nil
url.fragment #=> nil

URI::SshGit.build(
  userinfo: 'git',
  host: 'github.com',
  path: '/packsaddle/ruby-uri-ssh_git.git'
).to_s
#=> 'git@github.com:packsaddle/ruby-uri-ssh_git.git'

# Utility method
ssh_protocol = 'git@github.com:packsaddle/ruby-uri-ssh_git.git'
git_protocol = 'git://github.com/packsaddle/ruby-uri-ssh_git.git'

::URI::SshGit.ssh_protocol?(ssh_protocol) #=> true
::URI::SshGit.git_protocol?(ssh_protocol) #=> false
::URI::SshGit.ssh_protocol?(git_protocol) #=> false
::URI::SshGit.git_protocol?(git_protocol) #=> true

# Usage
git_clone_url = '...'
if URI::SshGit.ssh_protocol?(git_clone_url)
  parsed = URI::SshGit.parse(git_clone_url)
else
  parsed = URI.parse(git_clone_url)
end
parsed.host
parsed.path

感想

追記ここから: 2015-03-06 3:28
バグ作りこんだので, Utility部分は削ってインターフェース変えます。
追記ここまで

うーん… packsaddle/ruby-uri-ssh_git.git を parseするときに /packsaddle/ruby-uri-ssh_git.git に読み替えてるんだけど、ここが1対1のマッピングじゃない時に(foo/bar.gitが/data/foo/bar.gitですとか)情報が欠落してて破綻する。が、ひとまずgithubとbitbucketはこのルールでいいっぽいので良いとしておこう。あとURIがらみの初めて書いたのでhookするぽいんとがよくわからん。クラスとモジュールの構成もうまくないけど、必要なら誰かが直すでしょう… というかssh形式のurlをparse出来る何かがあるはず。

nodejsだとssh-url使うとよさげ
あとssh git url parse で調べてると、npmまわりのfetchしたりのissueがいろいろ出てくるので、普通にparse出来るのかもしれない。未確認。

参照

gitの思い出

git, agile, ruby, startupに `自分が` bet するぶんには好きでやってるからどうでもいい

あとえいや!でやってる以外のことは保守的考え 老害まっしぐら

ゆるやかに死ぬんじゃないかなーと思うけど
どうでもいいから食える > かっちょいいけど食えない

git や rubyを積極的には薦めてない
やりたい人には積極的に教えることを厭わない

教えた遍歴1 2010年6-8月ぐらい
アジャイルな開発をチームでやってみた(2010年版)

相手 エンジニアs 5人ぐらい? 自分のgit習熟度もいまいちで複数者の開発で起きるべきことが起きるべくして起こった

社内にgitosis入れてもらったので、それで開発
「まあsvnみたいなもんです」 => 教えてない!!
masterに入れるだけでレビューするでもなかった ツールは開発を規定しない!
gitの使い方はめちゃくちゃだったけど、それ以外はそのときの僕らのキャパシティ+アジャイル的にはうまくやれてたんじゃないかなあ
今から見てアラ言っても意味ないし

教えた遍歴2 2010年10月ぐらい
理由 別の会社がgitで開発してた
相手 エンジニアs 3名ぐらい たまたまだけどリードエンジニアみたいな人が多かった
あんまり触ったこと無さそうだったけど最低限はとっとと覚えてた => 教えてない!!
自分はcommitの粒度が必要以上に細かいので、それをgit-svnで潰すとsvn的にはちょうどいい粒度になってたんだけど、git to gitなのできにせずpushしたりしてたので今思うとひどいことをした

教えた遍歴3 2012年8月ぐらい
相手 デザイナー
「machidaみたいになりたいんだけど」「黒い画面見ろ」
「git覚えたいんだけど」「githubやれ」
「github覚えたいんだけど」「pull request送れ」
「次は」「免許皆伝!教えるものはもうなにもない」 => 教えてない!!

github楽しいか??
楽しい => 別に => 楽しい => 別に
今「別に」期
何者でもない他人のコードなんて見ないっすよ

「厭わない」どころか教えてないことが判明したのでいい話だった。

out of dateなgit-svnエントリー雑感

ウノウラボブログの自分の書いたエントリー大好きっ子なので見返してた。読み返すまで自信あったつもりなんだけど改めて見るとうーんと思った。やっぱり古くなるね。

ウノウラボ by Zynga Japan: git-svn駆け込み寺

素直にgit使うか素直にsvn使うのがいいと思う。
svn触ることってもう無いと思う。あと仕事ではsvn-externals地獄がさばけなくて途中からgit-svn使わずにsvnを生で使ってた。merge-infoが意図通りにつかなくて苦戦したのもあった。今やるならmerge –no-commit はありえねーなと思った。コミットヒストリー雑に崩すのは無い。たしか、mergeのコミットが自動メッセージで入ってしまい、それが嫌でそうした気がした。最後のメッセージが気に入らないだけならgit commit -v –amendしましょう。もしくはこんな感じ?tag振らなくてもgit reflogで戻ればいいかな。

$ git tag ‘before-merge’
$ git svn rebase
$ git merge topic-branch –no-ff
$ git tag ‘before-rebase’
$ git rebase -i HEAD~n
$ git svn dcommit

や、git svn rebaseやgit svn dcommitって大雑把すぎて嫌かなあ。git使っててもgit pullってカチャカチャターンって気分の時しかしないもんなー。他人のライブラリフォークしてて自分で変更加えてない時か、そんなの覚えてないとき。自分で変更加えてたらgit pull –rebaseかgit fetch originして手元でmerge かrebaseするし、pushはgit push foo bar:baz まで指定するよね。

.gitconfig にinclude ディレクティブ真似で捗った

.gitconfig にinclude で捗る話。マネしてみたらはかどった。

.gitconfigにinclude書くと捗る – かるぱねるらすたいる

同じ事だけどglobalなファイルを読み込んで、localなもの、環境依存のものだけは直書きするといい感じ。
https://github.com/sanemat/dotfiles/blob/master/.gitconfig
stackoverflowに~や$HOMEは展開しないよって書いてあったので。

source foobar 的な再読み込みの話。どうやって再読み込みするのかと思ったけど、試しにglobalな方にalias追加して保存してみたら、git のsub command使えるようになった。あとgit-completion.bashで補完もされた。毎回全部読んでるのか。git hahaha

hub clone を取り戻せ

$ hub clone で作った 手元のリポジトリと $ hub fork でgithub に作ったリポジトリを新しいマシンなど別の場所で取り戻す場合。

具体的に https://github.com/CHH/php-build , https://github.com/sanemat/php-build での話。

結論

$ hub clone CHH/php-build
$ cd php-build
$ hub remote add -p sanemat

今回の前提

clone元には書き込み権限ない
gitをhubでwrappingしてない
hub clone, hub fork にremote name を合わせる

実際にやったこと

自分のリポジトリ見てておもむろにclone
$ git clone git@github.com:sanemat/php-build.git
//ここでoriginは github.com:sanemat/php-build.git
//upstream登録しなきゃ
$ hub remote add CHH
//あれ?
$ git remote rename origin sanemat
$ git remote rename CHH origin

おわり

最新っぽいものを選択していく重要さ

ライブラリを使うときのバージョン指定の話。最新っぽいものを選択していくのがメリット多いですね。ちょっと前まではgitやsvnでtagに参照張ってないのは何考えてるのか意味が分からないという発言をしてましたが、groongaだかのメーリングリストで”新しいっぽいもの”を選んでいく重要さについて話が出てて感化されました。メリット・デメリットを比較した上で、最新っぽいものを選んでいくのが利益を最大化するという。tagでバージョン指定するとどうしても下に固定されたまま動けなくなってしまう。例えばrailsなら ‘~> 3.2’, rubyなら ‘~> 1.9.3’って感じでゆるく最新がいい。一応動いてるから触りたくない、まま放置したときにバグフィックス・セキュリティフィックスきたらどうするのっと。マイナーバージョンなのかパッチレベルなのかはプロダクトによるんだけど、最新っぽいものを選んでいくのが幸せ度高い。社内ライブラリレベルならそこが開発最前線にはなっていない、という前提の上でmasterやtrunkでいいんじゃないかなーと思うようになった。

というエントリをここ半年ぐらいのうちに書いた気がするんだけど、どっかに行ったか見つからないので再書き下ろし。

Edited: 2012-05-10 8:44

これかああああ あとで書いてないじゃん! というわけで書いた。よし!

https://sanematsu.wordpress.com/2012/04/20/shibuya-rb-offline/
“svn:externalsで安易にtrunkを張ることの否について話もした。そこで話しそびれたけれど、一年半前はそう思ってたのだけれど、ここ半年ぐらいは”なんとなく最新っぽいものを使うこと(by groongaのひと)の是”に感化されて消極的是どころか積極的是側にいます。これはあとで書く。”

masterからpull request送ってしまったときの復旧方法1例

masterからpull request送ってしまったときの復旧方法メモ
spikeはtopic branchで行っていたものの、その前提としてdocumentの修正をしないと話し通じないなーと思って、masterでちょいちょいっと直して pull requestした。
そこまではよかったんだけど、pull request考え直したんだけど取り込まれちゃったとかそう言うのは置いといて、おれのrepositoryのmasterよごれちゃった、とおもってどうしようかあたふたしてた。

なんであたふたしてたかっていうと、”topic branch に変更したものを push すれば pull request に反映される” って読んだことあったから。
github で開発するなら pull request を使いましょうという話, zsh-users の設定を入れてみた。 – HsbtDiary(2011-10-17)
http://www.hsbt.org/diary/20111017.html

masterでpull request送っちゃったら、そのあとのmasterへのpushって…。とおもって、自分のremoteのmasterをrenameする方法とかupstreamの追従を切る方法とかいろいろググッてモヤモヤしてた。

最終的には、以下のように整えたい。
– forkした自分のリポジトリのmasterのupstreamは本家のmasterもしくはfeature-developmentのきれいなbranchにしたい。
– 自分のtopic-branchはそこから作成したい。
– 前送ったpull requestに(できれば)あんまり影響与えたくない

はじめ、自分のリポジトリのmasterにpushしたぶんをbranchに再pushしてから、remoteのmaster消して、upstreamからmasterつくり直そうとした。ら、消せません!

$ git push origin master:doc-bundle-exec
Total 0 (delta 0), reused 0 (delta 0)
To git@github.com:sanemat/sorcery.git
* [new branch] master -> doc-bundle-exec
$ git push origin :master
remote: error: refusing to delete the current branch: refs/heads/master
To git@github.com:sanemat/sorcery.git
! [remote rejected] master (deletion of the current branch prohibited)
error: failed to push some refs to ‘git@github.com:sanemat/sorcery.git’

default branch消そうとするとメンドイらしい。adminタブから操作しないとだって。それはめんどい。
Can’t remove remote branch in git – Super User
http://superuser.com/questions/294407/cant-remove-remote-branch-in-git

なので、別の手段をとる。
GitHubへpull requestする際のベストプラクティス – hnwの日記
http://d.hatena.ne.jp/hnw/20110528

自分のcommitぶん1個巻き戻して mergeしてpushしちゃえばいいんじゃない?っていう。push -f しないといけないのかなあ。pushしたものの歴史改変するといろいろまずいんじゃないかな。とかいろいろ考えたけどエラー出たら考えればいいってことで。
$ git remote add upstream https://github.com/NoamB/sorcery.git

$ git reset –hard HEAD^
HEAD is now at 7997cd8 Regenerate gemspec for version 0.7.7

$ git pull upstream master
remote: Counting objects: 99, done.
remote: Compressing objects: 100% (52/52), done.
remote: Total 76 (delta 56), reused 42 (delta 22)
Unpacking objects: 100% (76/76), done.
From https://github.com/NoamB/sorcery
* branch master -> FETCH_HEAD
Updating 7997cd8..3eb80bb
Fast-forward
Gemfile.lock | 36 +++—
README.rdoc | 10 +-
Rakefile | 1 +
VERSION | 2 +-
lib/generators/sorcery/install_generator.rb | 6 +-
lib/sorcery/controller.rb | 1 +
sorcery.gemspec | 139 ++——————
spec/Gemfile.lock | 5 +-
spec/README.md | 16 +-
spec/rails3/Gemfile.lock | 5 +-
spec/rails3_mongo_mapper/Gemfile.lock | 5 +-
spec/rails3_mongoid/Gemfile.lock | 5 +-
…/spec/controller_activity_logging_spec.rb | 12 +-
13 files changed, 72 insertions(+), 171 deletions(-)

さくっとpullできた。さくっとpush通った。-fなしに。

$ git push origin master
Counting objects: 99, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (74/74), done.
Writing objects: 100% (76/76), 7.63 KiB, done.
Total 76 (delta 56), reused 0 (delta 0)
To git@github.com:sanemat/sorcery.git
3f1e176..3eb80bb master -> master

おわり。
きれいに取り込まれてたから
衝突せずに済んだから
pull requestがcloseされてたから
pull –rebaseしてればひとつ巻き戻す要らなかった?
なんか問題起きてるけど気づいてない

などなどいろいろ考えられるけど、今回は杞憂でしたっぽいってことで。

If you use git submodule

You might want to connect tag. Neither branches nor master.
Because git submodule stands for specific commit hash. Not “master” and “head”. So if you select with master-head on git submodule, but in reality this is “master” at the time in the past.