読者です 読者をやめる 読者になる 読者になる

質問に答えてみる

リポジトリ見てたら、question.txt なるファイルを見つけたので、その質問に答えてみます。

hard オプションなしの git reset に何の意味があるの?

reset には、ファイルを指定する reset と、ファイルを指定しない reset の 2 種類があります。
で、hard オプションを持つのは、ファイルを指定しない方です。
まずはこちらから見ていきましょう。

ファイルを指定しない reset

ファイルを指定しない reset には、

  • soft
  • mixed
  • hard
  • merge
  • keep

と言う 5 つのモードがあります。
ここでは代表的な上三つを紹介します。
デフォルトは mixed で、これが質問にあった「hard オプションなしの git reset」です。

soft

このモードでは、HEAD のみ指定コミットの状態となり、インデックスも作業ツリーも変更されません。
これは、ベアリポジトリに対して「今のブランチを別の場所に動かしたい・・・」と言うときに使えます。
というか、その他の便利な使い方は思いつきません・・・

mixed

このモードでは、HEAD とインデックスは指定コミットの状態になりますが、作業ツリーの状態は reset 前のままとなります。
これは、「あ、さっきのコミット、add し忘れてる!」とか、「あ、さっきのコミットでテスト壊しちゃってる!」のような状況をやり直すのに最適な状態です。
なので、mixed モードは「今の状態からちょっとだけ違う状態のコミットを作り出したい」場合によく使います。
必然的に、指定するコミットは HEAD^ のような相対値を使うことが多くなるでしょう。


ひとつ前のコミットに対しては、git commit --amend があるため、あまり出番はないかもしれません。
また、更に前のコミットに対しては、rebase -i がより柔軟なため、これまたあまり出番はありません。
git-now の id:mzp (みずぴーさん) の拡張に --fixup というオプションがあって、そこで rebase -i を使わずに now コミットをまとめるために使われていたりします。

hard

このモードでは、HEAD もインデックスも作業ツリーも、全てが指定コミットの状態に変更されます。
ブランチがもともと指していたコミットに辿りつける他のブランチやタグが無かった場合、gitk で Ctrl-F5 をすると消えてしまったように見えるように、このモードではブランチを移動させます。
reflog を使うなどしてまた辿りつけるようにする (gitk で表示させる) ことは容易ですが、Git のオブジェクトモデルをあまり理解していないうちは使わない方がいいでしょう。

ファイルを指定する reset

ファイルを指定する reset は、git add の反対の動作をするコマンドです。
git add はインデックスに状態を書き込むコマンドですが、ファイルを指定する reset はインデックスへの登録をキャンセルするコマンドです。
git add 同様、-p オプションを持っていますので、「あ、git add hoge」ってしちゃったけど一部要らない修正も add されちゃった!」と言うときに、git reset -p hoge すると、対話的に reset することが可能です。

過去のコミットにしかないファイルを参照したくなったけど、どうやるの?

方法としてはいくつか考えられますが、好きな方法を使うといいでしょう。
ハッシュ値とパスを指定して checkout するか、gitk などの GUI を使うのがお手軽でいいのではないでしょうか。

過去のコミットを取り戻したくなったけど、どうやるの?

あるコミットで行った変更を、今の状態に対してもう一回行いたい、と言う場合は、cherry-pick を使いましょう。
そうではなく、作業ツリーの状態を過去のコミットの状態にしたい、と言う場合、

  • そのコミットに reset する
  • そのコミットを checkout する

の 2 通りが考えられます。
過去のコミットの状態にした後、また取り戻す前の状態に戻って作業する場合、どちらでもいいので好きな方を使うといいでしょう。
そうではなく、その過去の状態からさらにコミットしていきたい場合は、reset を使ってください。
この場合に checkout を使うと、辿りつけないコミットを伸ばしていくことになってしまいます。
ただし、reset を使うのは上でも述べたとおり、Git のオブジェクトモデルを理解していることが前提です。
そうでない場合は、そのコミットに新しくブランチを作り、それをチェックアウトするのがいいでしょう。

git checkout -b ブランチ名 ハッシュ値

のようにすると、それを一気に行ってくれます。

文字化けはどうすればいいの?

Software Design 12 月号を買いましょう!
このあたりは自分でもまとめたいところですね。

どれくらいの頻度でコミット、push すればいいの?

これは、どうやって運用しているかにもよるので一概には言えないです。
自分は、Redmine のチケットとトピックブランチを対応させ、そのトピックブランチの中でコミットを複数回やっています。
push に関しては、一つのトピックブランチが終了したら push する感じですね。