$shibayu36->blog;

株式会社はてなでエンジニアをしています。プログラミングや読書のことなどについて書いています。

gitを使ってみたまとめ(4)

前回は、ブランチの管理についてでした。今回は履歴を用いた作業についてです。


1.ログ表示の基本
 git logコマンドで今までのコミットのログを調べることが出来る。
$git log
$git log -p
$git log (コミット名)
$git log -3
1番目はこれまでのログをすべて表示、2番目は差分も表示、3番目はコミット名と一致するコミットのログを表示、4番目は最新のコミットから3つ表示を表している。


2.ログの範囲を指定
 git logコマンドではさまざまな範囲の指定法がある。
$git log --before="3 hours"
$git log --since="10 minute"
$git log (古いリビジョン名)..(新しいリビジョン名)
$git log (リビジョン名)..
$git log (タグ名)..HEAD
1番目は3時間以上前の履歴を、2番目は10分前以降の履歴を表示する。時間指定はいろいろな英語の表記が使える。例えば2010-02-21なども可能。3番目は二つのリビジョンの間にある履歴を表示する。(古いリビジョン)は表示されないので注意。4番目は(リビジョン名)から今までの履歴を表示する。HEADは省略可能ということだ。5番目は指定にタグも使えるということを示している。

 また、リビジョンの指定には相対表記を使うことも出来る。^(キャレット)は一つ前と言う意味。いくつ使ってもよい。~N(チルダと数字)はN個前のリビジョンと言う意味。例えばHEAD^とか、HEAD~10のような使い方が出来る。

 また表示方式の指定には--prettyオプションを使用する。例えば、
$git log --pretty=oneline
$git --pretty=format:"%h %s"
というような指定が出来る。1番目は一行表示、2番目はハッシュ値、コミットログの最初の行を表示という意味である。


3.差分の表示
 差分の表示にはgit diffコマンドを使う。
$git diff (リビジョン名) (リビジョン名)
$git diff (リビジョン名)
$git diff --stat (タグ名)
git diffコマンドには二つの引数が指定できる。二つのリビジョン、もしくはタグ間の比較を行う。また、引数一つを省略するとHEADとの比較となる。変更点の詳細を表示せずに、変更の統計情報を表示する。1番目は一般的な使い方、2番目は引数を省略した使い方、3番目はタグを使い、統計情報を表示する使い方だ。


4.コードの情報の表示
 そのファイルのある行を誰が書いたのか、そのようなことを調べたいときはgit blameコマンドを使う。
$git blame (ファイル名)
$git blame -L 3,6 (ファイル名)
$git blame -L 3,+3 (ファイル名)
$git blame (リビジョン名) -- (ファイル名)
1番目のコマンドはあるファイルのすべての行の情報を表示する。基本的にはその変更を行ったリビジョン名、その時のファイル名、作者とタイムスタンプが情報として表示される。2番目のコマンドはあるファイルに対して行を指定したい場合に使うコマンドだ。3番目のように相対表記もできるし、正規表現を使った指定もできる。4番目はあるリビジョンにおける情報を表示する。ファイル名の前に--を忘れないように。


5.履歴の訂正、削除
 間違えたコミットを訂正するにはgit commitに--amendオプションを付ける。
$git commit -C HEAD -a --amend
$git commit -c HEAD -a --amend
--amendオプションを使うには、コミット名を指定しなければならない。指定したコミットを現在の変更に置き換える。1番目は、一番最後のコミットを現在の変更に置き換える(ただし、-Cオプションによってコメントはそのまま)。2番目は-cオプションによってコメントを少し書き換えることができる。

 コミットを取り消すときには、git revertコマンドを使う。git revertはすでにあるコミットを巻き戻すコミットを作成し、それにより、そのコミットにおいてなされた変更を取り消す。

$git revert HEAD
$git revert -n (リビジョン名)
1番目のコマンドは、最新の変更を巻き戻す。このコマンドを実行すると同時にコミットもされる。2番目のコマンドは、-nオプションによってリビジョン名を巻き戻す変更を一旦ステージにのせる。これによって、いくつかの変更を同時に巻き戻すことが出来る。ただし、-nオプションでいくつかのコミットを指定する場合は、新しいものから古いものの順に指定する。また、-nオプションは変更をステージに乗せるだけなので、コミットする必要がある。

 変更をリセットするときにはgit resetコマンドを使う。上の巻き戻すやり方では、元に戻す変更をコミットするため、もともとのコミット履歴は残るが、こちらのやり方ではそもそものコミット履歴を消す。つまり、あとで、リセットした履歴を戻したくても戻せない。注意が必要である。
$git reset --soft (コミット名)
$git reset --hard (コミット名)
1番目のコマンドでは、以前のコミットをすべてステージングエリアに戻し、コミットされていない状態にする。2番目のコマンドでは、コミットを完全に削除する。2番目のコマンドは特に注意が必要だ。また、コミット名には、相対表記などももちろん使える。


6.履歴の変更
 コミットの履歴を変更したいときにはgit rebase -iコマンドを使う。主に、コミットの順番を変える、複数コミットを一つに圧縮する、一つのコミットを複数に分割する、などのことが出来る。

 コミットの順番を変えるには、以下のコマンド。

$git rebase -i (リビジョン名)
このコマンドを実行すると、指定したエディタが起動され、指定したリビジョンのコミットから現在のコミットまでのコミットの情報が表示される。コミットの順番を変えたいときには、表示されている情報の行を入れ替えて、エディタを終了することで実行される。

 複数のコミットを一つに圧縮する場合は、上のコマンドを入力したあと、表示されている情報で圧縮したいコミット情報の最初のpickの文字をsquashに変える。エディタを終了するとコミットメッセージを入力するよう促され、squashに変えたコミットとその前にあるコミットが圧縮される。

 コミットを複数に分割するには、上のコマンドを入力したあと、分割したいコミットのpickの文字をeditに変えて、エディタを終了する。そうすると、editの文字が書かれたコミットに到達したときに、一旦プロンプトに戻される。この時、変更点を書いてコミットしてを複数に分割して行うことで、コミットを分割できる。分割が終了したら、

$git rebase --continue
を実行することで、rebaseが完了する。


 ただし、今回のような履歴の変更を柔軟に行えるのはローカルリポジトリ内でコミットしているときに限ります。もし、共有リポジトリや他人のリポジトリと同期を取ってしまったら、簡単には履歴を変更しないほうが良いです。解決しにくい競合が発生するようです。