Git 2.13が公開されました (英->和訳)

Git 2.13.0が公開されましたね。GitHubが最近[つぶやいた記事](https://github.com/blog/2360-git-2-13-has-been-released)を、本当にサクッと翻訳してみたので、編集リクエストをよろしくお願いします。
「は」と「が」とか、不自然に感じてしまったら申し訳ないですが、もしGitについての新しい情報が伝わればと思います。

# Git 2.13.0は公開されました
オープンソースであるGitプロジェクトはGit 2.13.0を公開し、[65人以上](http://public-inbox.org/git/xmqqa86lzifl.fsf@gitster.mtv.corp.google.com/)が機能を追加したりバグを直したりしました。その機能をもっと詳しく説明する前に、セキュリティに関する短い報告があります。

自分のGitホスティング・サーバーを使用していれば、`git shell`プログラムでは、信用できないGitのユーザがリモートホストでシェルコマンドを実行できてしまうという脆弱性をGit 2.13が直してくれます。これはホスティング・サーバーを使用し、特に`git shell`を設定した場合のみです。「よう意味が分からん」人には気にしなくていいはずです。一応、詳細は[こちら](http://public-inbox.org/git/xmqq8tm5ziat.fsf@gitster.mtv.corp.google.com/)です。Github.comもGitHub Enterpriseも`git shell`を使用していないので、影響を受けません。

ハァ...報告が終わったということで、楽しい部分を紹介しましょう！

# SHA-1衝突判定
あっ、楽しいって言ったっけ？ごめん、それはまだでして...

聞いたことがあるかもしれませんが、最近はある研究者たちがSHA-1（Gitが使っているオブジェクトを認識するためのハッシュ機能）の[初めての衝突](https://shattered.io/)を発見しました。このテクニックを使用し、Gitのユーザに対する衝突攻撃が行われたことでしょう。運よく、その同じ研究者たちがこのテクニックを駆使して攻撃しようとしている内容を検出できる方法を提供してくれました。３月に、GitHub.comはそういう衝突攻撃を防ぐために、[その方法を使いはじめました](https://github.com/blog/2338-sha-1-collision-detection-on-github-com)。

Git 2.13にも同じような変更があり、衝突攻撃の恐れのあるオブジェクトを検出し拒否します。衝撃を判定するSHA-1はもうデフォルトとなっています。そのコードはGitに入っていますので、他のプログラムをインストールする必要はありません。この実装は他の方法と比較的に遅いですが、大体のGitの運用においては、全体的にわずかな影響しか受けません（なぜかというと、GitはSHA-1のハッシュを計算する時間はそもそも短いからです）。

他の衝突判定ニュースなんですが、Gitでより強力なハッシュアルゴリズムが使えるように、ハッシュの新しい関数を扱うコードベースの遷移の準備の計画がなお進んでいます。

[[衝突判定](https://github.com/git/git/compare/fa13fd174f463663ffbc1feef857089fddb4b157...e6b07da2780f349c29809bd75d3eca6ad3c35d19)、[SHA-1の遷移 1](https://github.com/git/git/compare/0a4ae91d1cf72b1185a46e5f072ac6b25b92350b...e86ab2c1cd60ec4b9214e5cd8450a474fa175f5c), [SHA-1 遷移 2](https://github.com/git/git/compare/c703555cc89cf6aedf549a1233b242d8cb8e0f20...e239dabb1465d3ff927840b4fff15150a2170b4e)]

# より便利なpathspec
Gitでこうやってパスの引数を渡したことがあるかもしれません：

```
$ git log foo.c
$ git grep my_pattern program.rb
```

でも、Gitにとっては`foo.c`と`program.rb`という引数の正体は<i>[pathspecs](https://git-scm.com/book/ja/v2/Git%E3%81%AE%E5%86%85%E5%81%B4-%E7%92%B0%E5%A2%83%E5%A4%89%E6%95%B0)</i>、パスのマッチを行う、特にGitのパターンであることを知っていましたか？絶対パスでも、接頭詞でもワイルドカードでもPathspecsとして使えます：

```
$ git log Documentation/      # Documentation/ ディレクトリの下にある全てのもの
$ git log '*.c'               # ツリーの中にある全てのCのファイル
```

まして、強力な拡張シンタクスがあります。`:(magic)`で始まるpathspecsは特別のマッチ機能を有効にします。それらのリストが[git help glossaryのpathspecのところ](https://git-scm.com/docs/gitglossary#gitglossary-aiddefpathspecapathspec)に記載してありますが、ここでその中の何個かを見ていきましょう。

例えば、grepでファイルを除外したいという時は、`:(exclude)`を使います：

```
$ git grep this.is.a src
src/foo.c:this is a C file
src/foo.rb:this is a ruby file

$ git grep this.is.a -- src ':(exclude)*.c'
src/foo.rb:this is a ruby file
```

この例ではいくつかの気づくべきことがあります。１つ目は、分離するために `--`（ダブル・ダッシュ）をpathspecの後に置く必要がありました。多くのGitのコマンドは改訂（revisions）とpathspecの組み合わせを引数として受けるからです。完全なシンタクスはこうです：`[<revisions>] - [<pathspecs>]`。ダブル・ダッシュが抜いていると、Gitは全ての引数が、ファイルシステムの中にある有効なオブジェクト名かファイルかをチェックします。でも、このexcludeのバターンはどちらでもないです。そのために、ダブル・ダッシュがないとGitは諦めて文句ばかりを言う（将来のGitのバージョンではこれが変わる可能性があります。`*.c`みたいなワイルドカードもこのような問題があったけど、そのワイルドカードをpathspecとして扱うためにルールが緩くされました）。詳細は`git help cli`([リンク]((https://git-scm.com/docs/gitcli)))で確認できます。

気づくべき２つ目のことは、`:(exclude)`を書くのが面倒ですし、シェルでクオートに囲む必要があります。でも、解決方法があります：pathspecの短文式魔法。`exclude`の短文式は`!`（ビックリマーク）です。`.gitignore`のファイルみたいにGitの他の部分と似ているから覚えやすいです。

```
$ git grep this.is.a --src ':!*.c'
src/foo.rb:this is a ruby file
```

これは`exclude`より短いですけど、多くのシェルではビックリマークが履歴拡張を発生させますから、シングルクオートを書く必要はまだ残ってます。Git 2.13では`^`（カレット）がビックリマークの類語になっていますので、クオートで囲まずに同じことができます：

```
$ git grep this.is.a --src :^*.c
src/foo.rb:this is a ruby file
```

ふゎ〜、すっきりしましたね。普段はワイルドカードの`*.c`をシェルで書く時にクオートで囲む必要がありますけど、プラクティスとしては上記の方法が使えます。`:^`で始まって`.c`で終わるファイルがない限り、シェルはワイルドカードがどんなファイルにもマッチしないことを判定し、そのままGitに渡します。

だが、それだけではない！Git 2.13はgitattributesの値によってファイルを選択できる`attr`トークンを追加しています。例えば、Git LFSを使っていたら、それを設定するファイルのリストを表示したい時：

```
$ git ls-files
.gitattributes
README
video.mp4

$ git ls-files ':(attr:filter=lfs)'
video.mp4
```

というのができます。

ファイルを１つのグループにまとめるためにattributeを定義することもできます。attributeを定義し、そのattributeでファイルを選択できます：

```
$ echo 'libfoo/ vendored' >>.gitattributes
$ echo 'imported-tool/ vendored' >>.gitattributes
$ git grep -i license -- ':(attr:vendored)'
```

実は`attr`と`exclude`のトークンを組み合わせられます：

```
$ git grep foobar -- ':(exclude,attr:vendored)'
```

トークンである`attr`はまだ全てのコードにおいてサポートされていないことに注意してください。いくつかのコマンドは「`attr`が使えない」と報告しますけど、これは将来のGitのバージョンで拡張される見込みです。

[[negative pathspecs](https://github.com/git/git/compare/fb75e317614c1d6aec2ef5b65775a603db8f68da...859b7f1d0e742493d2a9396794cd9040213ad846), [attribute pathspecs](https://github.com/git/git/compare/60cf6cd71af2c3a530ac9fad57579a7b10e862ee...c5af19f9ab4cd8582689ca9d9c84f188f4442d10)]

# 条件付きの設定
Gitの設定システムは優先する階層があります：システムの段階、ユーザの段階、レポジトリの段階、それとも個人的なコマンド呼び出し（`git -c`を使う（[リンク](https://git-scm.com/docs/git#git--cltnamegtltvaluegt)））オプションを設定できます。一般的に、より厳密な場所で見つかったオプションは比較的に厳密でないオプションをオーバーライドします。レポジトリの`.git/config`に`user.email`を設定したら、ユーザの段階で設定された`~/.gitconfig`をオーバーライドするかもしれません。

でも、レポジトリの集まりに対して１つのオプションを設定し、また別の集まりに対して別のオプションを設定する必要がある場合はないですか？例えば、普通の仕事で自分の名前とメールを使ってコミットするけど、オープンソースでは別の名前とメールを使う場合。ホームディレクトリにあるconfigではオープンソースの資格をユーザの段階ので設定してから、仕事のレポジトリでオーバーライドできます。でもそれを一々アップデートするのは面倒だし、もし新しいレポジトリの設定をするのを忘れた場合、違う資格でコミットしてしまうこのになります！

Git 2.13は[条件付き設定インクルード](https://git-scm.com/docs/git-config#_includes)を提供しています。今はレポジトリのファイルシステムパスの認識しかサポートされていないけど、それで充分です。ホームディレクトリの`~/.gitconfig`で２つの条件付きインクルードを設定できます。

```
[includeIf "gitdir:~/work/"]
  path = .gitconfig-work
[includeIf "gitdir:~/play/"]
  path = .gitconfig-play
```

これで、そのファイルに適切なオプションを設定できます：

```
$ cat ~/.gitconfig-work
[user]
name = Serious Q. Programmer
email = serious.programmer@business.example.com

$ cat ~/.gitconfig-play
[user]
name = Random J. Hacker
email = rmsfan1979@example.com
```
`work`か`play`のディレクトリの中にあるレポジトリでは、適切な設定のオプションが自動的に適用されます。

[[条件付きインクルード](https://github.com/git/git/compare/45cbc37c5f84fadd78cccf6b2ea82a9ef251cdc6...3efd0bedc6625a6b194c1f6e5f1b7aa7d8b7e6bb)]

# その他
・`--decorate=auto`は`git log`のデフォルトとなりました。ユーザのターミナルに出力が送られてくる時、ブランチかタグに指定されたコミットはそのブランチの名前で修飾されます。（[ソース](https://github.com/git/git/commit/d9758cf81cd8af42a7ab55dc3c1a889d9ddd3f81)）
・`git branch`の出力ルーチンは`git for-each-ref`や`git tag`が共有している`ref-filter`に移りました。ということは、カスタムな出力を実現するために`git branch --format=`を使うことができます。代入のリストを閲覧するには`git help for-each-ref`([リンク](https://git-scm.com/docs/git-for-each-ref#_field_names))を参照してください。ところで、このパッチを作ったのは、２０１５年にGitのGoogle Summer of Codeの学生だったKarthik Nayakさんです。２年前に、GSoCでのプロジェクトとして紹介した`ref-filter`はほぼ完成していた状態だったにもかかわらず、彼はまだ貢献しつづけています。Great work!([ソース](https://github.com/git/git/compare/a411726930a6fc97d5a1f62d8d8d59b8587b10f2...44a6b6ce1777f587c318008fe59b901a296f5326))
・`git branch`, `git tag`, そして`git for-each-ref`全てがもう既にあった`--contains`オプションと更に、`--no-contains`オプションが使えるようになりました。バグ（それともbugfix）が<b>ない</b>タグかブランチを調べられる機能です。
・`git stash`はpathspecsを受け取れるようになりました。作業のツリーの一部としてこのstashを作成できます。コミットをきれいにするために変更をいじる時には便利です。（[ソース](https://github.com/git/git/compare/ae900ebd71b58c12356674228ce99e6673da3dec...9e140909f611fff720efc914b7186b8e4ab722cd)）
・`@{upstream}`、`@{u}`、と`@{push}`という特別のブランチ名は小文字と大文字を区別しないようになりました。これの便利な点といえば、多くのキーボードでは`@`と`{`を入力するためにshiftを押す必要があるから、大文字の`U`を入力してしまいます。このアップデートではshiftキーを<b>押し続けまくってもいいぞ</b>（[ソース](https://github.com/git/git/commit/244ea1b5e49081530e0ba5c717db1fdbe2bda73e)）
・過去のGitのバージョンでは、`checkout`、`grep`、と`ls-files`みたいなコマンドがサブモジュールにおいて再起を使うことができるようになっています。`git status --short`もサブモジュールについて情報を報告できるようになりました。[[ソース](https://github.com/git/git/compare/ff8b7e63dede832e8a02ce632fc70dcb59bf2681...25804914fa3661549cb4017fd0d127b9b626fc69)、[ソース](https://github.com/git/git/compare/ffac48d093d4b518a0cc0e8bf1b7cb53e0c3d7a2...e6fac7f3d3e313a93fe9b1243917669267b33153)、[ソース](https://github.com/git/git/compare/2bee56be7e241db75774fc6a7a235b8125936943...75a6315f7416a2fd559d0b0c7352b4f1cd10e186)、[ソース](https://github.com/git/git/compare/584f8975d2d9530a34bd0b936ae774f82fe30fed...40069d6e3a195c8c2414ea60ed75b84ae47f88a1)]
・最近のGitのバージョンはレポジトリの発見と初期化においてのコーナーケースを直しています。その作業の最後のステップとしては、Git 2.13は見逃されたケースをキャッチするアサーションを取り入れています。数ヶ月の間に渡って開発版でこれをテストしてきたので、出てくるはずはないです。でも、`BUG: setup_git_env called without repository`は出てくるかもしれません。もし出たら、[バグレポート](https://git-scm.com/community)を送るように、ご協力をよろしくお願いします。（[ソース](https://github.com/git/git/commit/b1ef400eece473f83f39980c54f67e3e7d202538)）

# 諸事万端
700コミット以上からなるGit 2.13で追加・変更した項目は、上記にいくつかしか書いてないです。リスト全体を閲覧するには、[完全リリースノート](https://github.com/git/git/blob/v2.13.0/Documentation/RelNotes/2.13.0.txt)を参照してください。