Gitと結び
日本の伝統工芸で「組紐(くみひも)」というものがあります。組紐は、複数の糸を編むことで、より丈夫で、より美しい紐を作っていきます。この組紐、世界中で注目されている映画「君の名は。」で取り上げられています。劇中では、おばあさんがその伝統を伝えるために次のような言葉を述べています。
よりあつまって形を作り、捻れて絡まって、時には戻って、途切れ、またつながり。それが組紐。それが時間。それがムスビ。
このセリフを聞いて、これはGitのことではないかとピンときました。チームメンバーの成果がcommit(以下コミット)としてよりあつまり、プロダクトとなり、バグの混入や間違った仕様をrevertにより戻したり、branchで一旦masterから切れたコードがmergeで繋がったり。これは、まさにGitではないでしょうか。
また、GitHubの登場により、Gitは単なるバージョン管理ツールではなく、人と人を繋ぐツールとして発展してきました。GitHubで公開したコードが他の人によってフォークされて必要な機能が実装されたり、その機能がプルリクエストで元のコードに戻ったり。さらにコード同士を繋げるだけでなく、オンラインのコミュニケーションを通して出会った人々を同時に繋げるようになりました。まさにGitは、ムスビのツールと言えるでしょう。
普及したGitとその課題
さて、筆者は『Gitポケットリファレンス』の第1版を4年前に執筆しました。その当時、Visual StudioなどはGitを利用するには別途プラグインが必要でした。それが今や、Visual Studioが標準でGitの機能を提供する他、バージョン管理機能では競合するTeam Foundation ServerでさえGitのリポジトリをサポートするようになりました。もちろん、Xcode、Android Studio(IntelliJ)、Eclipseなど主要なツールはGitをサポートしています。
事実上デファクトスタンダートとなり、Gitの利用者は爆発的に増えていきました。しかしながら、より幅広いユーザ層への利用が裾野が広がった反面、十分にGitを使いこなせていないユーザも増えてきている印象があります。Gitのバージョンが上がり様々な点で進化してはいますが、わかり難さについては、以前のままなことが原因のようにも思います。
また、開発と言えば、Windows上で行う風習があったのがmacOSの利用が増加しました。これにより、改行コードが異なることで起きる問題や、macOSは濁点付きの文字を2文字で表現しますが他のプラットフォームでは1文字で表現することで発生する問題など、利用OSの混在によるトラブルも以前より増えてきています。
そこで本稿では、Gitをもう一歩利用するためのTipsをいくつか紹介します。
コミットを失敗したときはどうすればよいか
コミットを失敗したとき、修正したくなることがあります。Gitにはコミットを修正する方法がいくつかあり、どれを使えばよいのか紛らわしいです。ここでは、直前のコミットを修正したいときの対処方法を紹介しましょう。
まず、修正したいコミットがリモートリポジトリにプッシュされているかどうか調べます。次のコマンドで、まだプッシュしていないコミット一覧を確認できます。
$ git log --oneline @{u}..HEAD
ac6d81a 修正したいコミット
d56c1c8 ユーザデータベースのテーブル名の誤りを修正
ここで、何も表示されない場合は次の①に進みます。修正したいコミットが表示された場合は②に進みます。
なお、HEADは、作業しているブランチの先頭のコミット(直前のコミット)を指します。
① 修正したいコミットを既にリモートリポジトリにプッシュしてしまった
既にプッシュしてしまった場合、過去のコミットを修正してプッシュしなおすと、他の人がリモートリポジトリと同期が取れなくなります。そこで、誤ったコミットはそのままにして、git revertを使ってコミットした編集を取り消すコミットを作成します。
$ git revert HEAD
git revertは新しいコミットを作成するため、機能的な不具合を引き起こすようなコミットのみに利用しましょう。コミットメッセージのタイポなどには利用しないほうがよいです。
② 修正したいコミットをリモートリポジトリにまだプッシュしていない
まだプッシュしていないコミットだった場合、ローカルリポジトリで修正できます。直前のコミットの修正は、修正したい内容に応じて次の手順で行います。
コミットメッセージを誤った場合は、次のコマンドで直前のコミットをやりなおし、メッセージを修正します。
$ git commit --amend
コミット時にファイルの追加漏れがあった場合は、git addでファイルをインデックスに追加した後、--amendオプションでコミットをやりなおすことで、直前のコミットにファイルを追加できます。
$ git add addfile.txt
$ git commit --amend
コミットを取り消し、もう一度やりなおす(コミットしたファイルの変更は残す)場合は、次のコマンドでコミットする前の状態に戻します。変更した内容はそのまま残っているので、修正したい箇所を修正し、git add/git commitでコミットをやりなおします。
$ git reset HEAD^
コミットを取り消し、もう一度やりなおす(コミットしたファイルの変更も戻す)場合は、次のコマンドでコミットする前の状態にします。
$ git reset --hard HEAD^
環境依存のファイルがうまく扱えない
テストなどを行うときに、環境毎に変更が必要なファイルがあります。例えば、試験をするホストのIPアドレスであったり、データベースサーバの設定であったり、試験をするユーザのユーザ名やパスワードであったりします。
このようなファイルは、リポジトリからクローンした後に変更する必要があります。しかしGitで管理していると変更ファイルとして識別され、コミット時にいつもコミット候補のファイルとして表示されたり、うっかり誤ってコミットしてしまったりと煩わしいです。そのような場合は、次のようにgit update-index --skip-worktreeを利用すると、一時的にGitのバージョン管理からファイルを外すことができます。
$ git update-index --skip-worktree config.xml
マルチチプラットフォーム化によるトラブル
macOSで編集したファイルにWindowsで行を追加すると、次のように改行コードが混在することがあります(改行はエスケープ文字で表現)。
はじめまして\n
このファイルはmacOSで作成しました。\n
この行はWindowsで追加しました。\r\n
おわり\n
最初に作成した時点ではすべての改行が\nですが、Windowsで追加した行が\r\nとなり、改行コードが混在しています。エディタによっては、改行コードが異なる部分を正しく表示しなかったり、コンパイラやインタプリタによっては正しく動作しないことがあります。
Windows版のGitにはテキストファイルの改行コードを変換する機能があるので、これを使うと問題は解決できます。
$ git config core.autocrlf auto
上記の設定を行った場合、改行コードが\nのファイルがあるとWindowsでクローン・チェックアウト時に自動的にWindows標準の改行コード\r\nに変換します。また、コミット時には\nに変換してコミットします。
この機能により、リポジトリ内のテキストファイルの改行コードを\nに統一できトラブルを防ぐことができます。
さいごに
本稿では、Gitの意味と課題を振り返りながら、Gitを使いこなすためのTipsを紹介していきました。筆者は前述の通り『Gitポケットリファレンス』を執筆しましたが、出版から4年経ちGitのバージョンやGitを取り巻く状況も色々変わってきました。
著者としても折角執筆した書籍の情報が古くなっていくことに対して焦りを感じていましたが、この度『改訂新版 Gitポケットリファレンス』として内容をアップデートし、昨年(2016年)の12月1日に出版できました。
改訂版では、最新のGit 2.xで追加されたコマンドやオプションの紹介はもちろんのこと、最近コミュニケーションツールとして使われるようになったSlackとの連携や、GitLab/GitBucketなどのGitリポジトリサービスの紹介、様々なノウハウなども全体的にアップデートし、時代の流れにあったより実用的な書籍として改訂しています。ぜひお手に取ってご覧ください。