ラベル Git の投稿を表示しています。 すべての投稿を表示
ラベル Git の投稿を表示しています。 すべての投稿を表示

2015年7月26日日曜日

Gitを使う上で便利なzshの設定

僕がzshrcに設定している Git 用の設定を紹介する。
  • プロンプトにブランチ名を表示
  • run-help をカスタマイズ
あんまりヘビーなカスタマイズはしてなくて,必要最低限,って感じだ。

まずは「プロンプトにブランチ名を表示」から。

2015年3月29日日曜日

Gitの最初の姿

この4月で、Gitが誕生してからちょうど10年になるようだ。
10年前、つまり一番最初のGitはどのようなプログラムだったんだろう?

当然だけど Git プロジェクトのリポジトリには10年前の最初の姿が e83c516 というコミットとして記録されている。
% git log --max-parents=0
commit e83c5163316f89bfbde7d9ab23ca2e25604af290
Author: Linus Torvalds <torvalds ppc970.osdl.org>
Date:   Thu Apr 7 15:13:13 2005 -0700

    Initial revision of "git", the information manager from hell
# --max-parents=0 は親のないコミット、つまりルートコミットを探す方法だ。
# もちろんこれが Linus が書いた本当に最初のツリーとは限らない。 Gitリポジトリから辿れる最初、という意味だ。
今回はこの当時の姿について少し見てみようと思う。

2015年2月15日日曜日

rebase して FF マージすることによる一直線の履歴は本当にわかりやすいのか

Git でトピックブランチを統合ブランチにマージする直前、最新の統合ブランチの先端にrebaseしたうえで FF (Fast-forward)マージすることで、見かけ上の履歴は一直線になる。 このような一直線の履歴が「わかりやすい」と解説されていることが多いんだけど、これは本当だろうか?

実は、このような見かけだけ「一直線」の履歴はむしろトピックの範囲が不明確になるのでわかりにくいんだ。

2015年1月30日金曜日

Gitでpush -fせずにmasterの間違いを修正する方法

そんなものはない (タイトルは釣りだ。ゴメン)。

でもよく聞く「ミスに気づいて、思わず master に push -f しちゃった」という話は、実はある運用方法で簡単に防ぐことができるんだ。 その運用方法とは・・・

2014年6月28日土曜日

gitworkflows(7)を図解したスライドをアップしました

前回に引き続き、こちらも会社の読書会でGit関連本の番外編として実施したgitworkflows(7)の解説資料(の加筆修正版)です。

マニュアルからすると講義用にかなりつまみ食い的な内容になってます。
副読本的な位置づけでマニュアルを読むのも良いかなと思います。

Gitの布教などにお使いください。

2014年6月24日火曜日

コンセプトから理解するGitコマンド

Gitのコマンドってわかりにくい、というかとっつきにくいものや、役割が複数あって覚えにくいものとか多い気がします。

でもGitが内部でデータ(コミットやツリー、ブロブ等いわゆるGitオブジェクト)をどのように扱っているかを理解すると、コマンドの役割や挙動の理解も進むのでは、と思ってスライドを作りました。

2014年4月27日日曜日

Git 2.0 rc1

先日(2014/04/26) Git 2.0 の rc1 (Release Candidate 1) がテスト用に公開されました

来るリリースに向けた変更点で大きいのは、やはり 1.9 までとの非互換性です。具体的には
  • ブランチ指定なしで git push した場合のデフォルトの挙動が 'simple' になった
  • サブディレクトリで git add -u または git add -A したとき(pathを明示的に指定しない場合)、ツリー全体が対象になった
  • git add <path> したとき(<path>を明示的に指定したとき)の挙動が git add -A <path> と同じになった
あたりです。(実は小さな非互換な変更が別にひとつあります。詳細はリリースノート草稿をどうぞ)

1番目はすでにいろいろなところで記事になっていて有名ですね。私としてはブランチ指定なしのpushをあまりしないので、特にどちらの挙動が便利という感覚はありませんが、simpleのほうが安全なデフォルトだと思います。

2番めは git commit などの挙動との一貫性という意味で、より統一された挙動になっています。

3番目はファイルを削除したあとでそのファイル削除をステージしたい場合、 git add <削除したファイル> とする(あるいはそれを含むディレクトリを指定する)だけで削除をステージできます。これまではgit add -A <削除したファイル> とするか、 git rm <削除したファイル>が必要でした。
ステージングには git add <path> だけで対応できるようになり、 git addはより「ステージングのためのコマンド」という性格が強くなったようにも思います。
削除だけではなく 非追跡ファイルも追加される、という点には注意が必要ですが、そうしたくなければもともと -u オプションがあるわけですから、特に先入観のない初心者にとって受け入れやすい挙動になったのではないでしょうか。

コマンドやオプションのややこしさを指摘されることもあるGitですが、今回のような非互換性を伴う変更を乗り越えて改善を続けており、今後の進化も期待が持てます。

なお、今回の非互換性の導入については、2.0での変更に向けてかなり以前から関係する挙動に警告を表示するなど、既存ユーザに配慮した移行がなされました。これは1.6の頃に非互換な変更を導入した際の反省に基づくものだそうです

他に1.9から追加された機能で個人的に気になるものとしては、

  • git rebase で '-' が '@{-1}' なブランチ名として解釈されるようになった(タイプ数が減るのは嬉しい。)
  • git config で --file - を指定すると値を標準入力から読み取れるらしい(スクリプティングなどで使う機会があるかも?)
  • git commit 時に常にGPG署名するための設定 "commit.gpgsign" が追加された。(これが必要な環境ってちょっと怖い。毎コミットについて改ざんも否認もできなくなるので嬉しいシチュエーションもありそう)
  • "pull.ff" 設定で pull --no-ff や pull --ff-only をデフォルトの挙動にできる。(ff-onlyは非メンテナ作業時 = ほとんどの場合に便利)
あたりでしょうか。(勘違いしてる可能性もあるので、正確にはリリースノート草稿を参照してください。他にもたくさんの新機能が導入されていますので、それらについてもリリースノート草稿を確認してもらうのが良いと思います)


さて、このまま大きな不具合などがなければ5月の中旬から下旬あたりには 2.0 正式リリースになると思います。今から楽しみですね。

2014年3月15日土曜日

「Git 2.0 がリリースされた」というデマ

「Git 2.0がリリースされた」という話がtwitterで広まっていましたが、2014/03/14現在、実際にはリリースされていません。
(2014/04/27追記: 2.0-rc1がリリースされましたので、もうすぐ本当に2.0がリリースされます→日本時間で5/29に当初予定より約2weekおくれでリリースされました)

「Git 2.0のリリースノート」「Git 2.0がもうすぐリリースされる」はまだしも、「Git 2.0がリリースされた」は完全に誤りです。

twitterで検索したところ、的確な内容をつぶやいているのは数人の方だけのようでした。正しい内容を最も端的に指摘されていたのは @uu59 さんの


だと思います。

これまでと同じようなリリース間隔(12weekごと)であれば、順調にいっても2.0のリリース時期は5月の第2週以降になりそうです。
2.0 のリリースノートについても実際に 2.0 がリリースされるまでには新機能・バグフィックスに関する記述が追加されていくと思いますので、今回話題になった時点のドラフト版とは厳密には異なるものになります。

ただ、今回の件は海外でも釣られた人が多かったようで「2.0がリリースされた」と記事にしてしまったニュースサイトもありました。ドラフト版リリースノートという、それらしい証拠っぽく見えるものがあったので釣られた人も多かったのかなと思います。

なお、1.8 シリーズまでは機能リリースが 1.8.x で、バグフィックスリリースが 1.8.x.y というバージョン番号が付けられていました。
先日リリースされた 1.9 シリーズもそうなるのかなと思っていたのですが、次回機能リリースが 2.0 (2.0.0) となると(※)、付与規則が変わったんですかね?

※ 2.0までマージしない約束になっていた、これまでとは互換性のない挙動を導入するトピックがnextからmasterにマージされたので、次回の機能リリースが2.0なのは確定のはずです。

2014/03/20追記:
やはり1.9シリーズからバージョン番号付与規則が変更されたそうです。これまでのバージョン番号はw.x.y.zでメンテナスリリースではzを、機能リリースではyを、大きな変更を伴う機能リリースではxを増加させ、wは本当に大きな変更のために予約されてきましたが、x.yzで十分じゃね?という話になったようです。1.9.1リリースの話とともに詳しい記述がメンテナHamanoさんのブログ記事 Git Blame: Git 1.9.1 にあります。

2014年2月28日金曜日

Gitで特定の関数の変遷だけを確認する(git log -L)

最近知ったのですが、 git log では特定の関数の歴史だけを見ることができます(たぶんGit 1.8.4 以降)。

やり方は
git log -L :<regex>:<file>
これだけです。git showのように、コミットメッセージとともに、<file>中で最初に<regex>にマッチする関数に関してのみdiffを表示してくれます。diffは関数の途中で省略されず、全体を1ハンクに収めるかたちで、見やすく表示されます。
-L オプションは複数回指定可能です。

関数名は現在のHEADの<file>の内容の中でマッチするものを指定する必要があります。HEADの内容でマッチさえすれば、歴史をたどっていく途中で関数名が変わっても、コンテキストから推測して最後まで(初めてその関数を追加したコミットまで)追跡してくれるようです。

どの言語における関数にも対応しているかどうかは確認していませんが、-L には <start>,<end>:<file> という指定も可能で、前述の書式では指定が難しい場合にも細かく開始地点と終了地点を指定できます。(<start>, <end>にはファイル内の行数、正規表現、オフセットなどが使えます)

うーん便利。

2014年2月14日金曜日

Gitで今作ったコミットを以前のコミットに半自動的に融合させる(rebase autosquash)

よく「トピックブランチにおけるコミットは、トピックに関連した内容のみ、論理的単位で小さく作れ」といわれますが、実際にコードを書いているときは最初から完璧だと思える一連のコミットをつくり上げるのは非常に困難です。

たとえば、「あー、この変更はさっきのコミットに含めておくべきだったな」とか。

2014年2月8日土曜日

コンフリクトしたマージの解消作業を再利用する(git-rerere)

前回前々回の記事では、nextのようなブランチを再構成する利点を解説しましたが、「再構成の利点はわかったけど、コンフリクトしたマージはrebaseしたらどっかいっちゃうのでできるだけやりたくない」という人も多いかと思います。

実はgitにはコンフリクトしたマージの解消方法を記録して、同じコンフリクトに対しては同じ解消方法を自動的に適用する機能があります。

それが git-rerere(1) です。rerereは REuse REcorded REsolutionの略みたいです。この機能はデフォルトでは無効になっているので、明示的に有効にしてやる必要があります。詳しい方法などは git-rerere(1) やrerereを解説したブログなどを参照すると良いと思います。

参考:
 - git-rerere(1)
 - unpushの日記: git-rerereのメモ

Gitのコミットグラフ(歴史)を綺麗に保つ効果(2)

前回に引き続き、綺麗な歴史を残す利点についてです。
今回は少し複雑な例を用います。

2014年2月6日木曜日

Gitのコミットグラフ(歴史)を綺麗に保つ効果

Gitではコミットグラフ(歴史)を綺麗にしておきやすいという特徴があります。

あまり気にしない人もいるかもしれませんが、どういったところが嬉しいのか簡単な例で説明してみたいと思います。

2014年2月4日火曜日

gitworkflowsの補足(2) - よくある誤解

gitwokflows(7)に関する補助的な解説その2です。

gitworkflowsについて、ありがちな誤解や質問について妄想してみました。なお、これはgitworkflows(7)を自分のプロジェクトに採用することを考えた場合の話で、Git本家でやっているワークフローそのものの話ではありませんのでご注意を。

gitworkflowsの補足(1) - gitworkiflowsを採用する目的

gitworkflows(7)についての補足記事です。

gitworkflowsを採用する目的、あるいはgitworkflowsを採用する利点は何よ?というところですが、これは一言でいえば「masterに綺麗な歴史を残す(残せる)」というものです。

2014年1月31日金曜日

Gitのブランチに別名をつける(symbolic-ref)

Gitのブランチに別名をつける方法を紹介します。

やり方は、
% git symbolic-ref refs/heads/<新しい名前> refs/heads/<参照先>
です。

以下解説。

2009年9月12日土曜日

ステージを理解して git をもっと便利に使う(git-add詳細情報)

ステージ(インデックスに変更を追加すること)について前回までざっくりと見てきましたが、第1回で紹介したコマンド git-add のマニュアルを日本語訳したので紹介します。

git-add(1)

git-add はステージを理解する上での要とも言えるコマンドなので、ひととおりオプションを眺めてみると、何か悟れるかも?

なお、原本は git-1.6.4.1 の時点でのマニュアルです。お使いのバージョンによっては存在しないオプションもあるかもしれません。新しいバージョンほどより便利になっているので、これを期に git://git.kernel.org/pub/scm/git/git.git から最新版を clone して使うというのも良い選択だと思います。


ステージというテーマでは今回が最終回になります。
gitに関する次回以降の記事は "easy branch easy commit" をテーマに何回かにわけてお送りしたいと思います。
ではでは。

2009年8月29日土曜日

ステージを理解して git をもっと便利に使う(その3)

前回から引き続き、「ステージを理解して git をもっと便利に使う」というテーマでお送りする、git解説記事の第3弾です。

まずは、前回までのおさらいです。

git にはリポジトリに格納された「最新のコミット」と「ワーキングコピー」の間に「index」と呼ばれる緩衝地帯が存在しています。チェックアウト直後は

「最新のコミット」=「index」=「ワーキングコピー」

ですが、ワーキングコピーを編集した後、git addにより編集内容がstage(indexに登録)され、

「最新のコミット」≠「index(+α)」=「ワーキングコピー(+α)」

となります。

% git add

% git add -p

を積極的に使うことで、編集内容を部分的にstageする/しないをコントロールし、1コミットの内容を洗練しましょう、というのが第1回の内容でした。

第2回はgit diffとgit diff --cachedの違いについて解説しました。

% git diff

は「index」と「ワーキングコピー」の差分を表示し、

% git diff --cached

は「最新のコミット」と「index」の差分を表示する、
という内容でした。

第3回はgit resetになります。

●git reset
実行例

% git reset

git resetを使うと、一度git addでstageした変更内容をindexから削除(unstage)することができます。

例として、
「ワーキングコピーの README と src/abc.c を編集し、git add -uで両方ともstageしたが、よく考えてみると別々にコミットすべき内容だった」
という状況を考えます。git statusで確認すると、以下のように表示されます。

kt@ume% git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD ..." to unstage)
#
# modified: README
# modified: src/abc.c
#

今回はREADMEだけをコミットし、src/abc.cはその後のコミットに含めることにしたとします。
この場合、git reset src/abc.cを実行することでsrc/abc.cをunstageできます。

kt@ume% git reset src/abc.c
src/abc.c: locally modified
kt@ume% git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD ..." to unstage)
#
# modified: README
#
# Changed but not updated:
# (use "git add ..." to update what will be committed)
#
# modified: src/abc.c
#

このとおり、src/abc.cは「Changes to be committed:」から「Changed but not updated:」に移りました。
これでgit commitしても変更が反映されるのはREADMEだけです。

git add -pによりファイルの内容を部分的にstageできますが、unstageはファイル単位でしかできないようです。
git add -pを間違えた場合は、一旦git resetして再度git add -pでstageしなおしましょう。

なお、上の実行例の「Changes to be committed:」の下の行にこんなコメントが書かれているのに気づいたでしょうか?

# (use "git reset HEAD ..." to unstage)

unstageのやりかたがそのものズバリ書いてあります。
もしgit resetを忘れてしまった場合にも「git statusの出力を見れば書いてある」ということさえ覚えておけば、どうすればよいか思い出せるでしょう。



●おまけ
前回紹介したgit diff --cached ってコマンドを打つのが面倒じゃありませんか?こんなときは git configで別名を定義しましょう。

kt@ume% git config --global alias.difc "diff --cached"
kt@ume% git help difc
`git difc' is aliased to `diff --cached'

上記の例では difc を "diff --cached" の別名として定義しています。
CVSやSubversionからの乗り換えユーザには以下のようなaliasもおすすめです。

git config --global alias.ad add
git config --global alias.br branch
git config --global alias.ci commit
git config --global alias.co checkout
git config --global alias.dif diff
git config --global alias.di diff
git config --global alias.st status