こんにちは、かつコーチです。
これまでGit編では、基本操作からブランチ、マージ、コンフリクト、履歴操作まで幅広く解説してきました。
最終回となる今回は、実務でよく遭遇するトラブルとその解決法を、まとめて確認していきます。
「あのときどう対処すればいいんだっけ」と迷ったときに、辞書的に見返してもらえる記事を目指しました。
よくあるGitのトラブルとは
道に迷ったときの戻り方というイメージ
Gitのトラブル対応は、慣れない道で迷子になったときの対処によく似ています。
道に迷ったとき大切なのは、パニックにならず「どこで曲がり間違えたか」を1つずつ確認することです。
Gitのエラーも同様で、メッセージをよく読めば「今どういう状態で、何を求められているか」がほとんど書かれています。
慌てて--forceのような強力なコマンドに飛びつく前に、まずは落ち着いてメッセージを読む。
これがトラブル対応の大原則です。
コミット・変更に関するトラブル
直前のコミットメッセージを間違えた
タイプミスのあるコミットメッセージを直したいだけなら、--amendが使えます。
# 直前のコミットメッセージだけを修正する
git commit --amend -m "正しいコミットメッセージ"
すでにpushしてしまったコミットに対して--amendを使う場合は、履歴が書き換わるため、前回・前々回で解説したrevertやrebaseの原則と同じく、共有ブランチでは慎重に扱う必要があります。
コミットし忘れたファイルがある
「コミットしたつもりが、1ファイル追加し忘れていた」というのもよくあるミスです。
# 忘れていたファイルを追加してから
git add forgotten-file.txt
# --no-editで直前のコミットにそのまま含める
git commit --amend --no-edit
これも直前のコミットを書き換える操作なので、pushする前に気づいた場合にだけ使うようにしましょう。
ブランチ・マージに関するトラブル
間違ったブランチで作業してしまった
「気づいたらmainブランチのまま、直接コミットしていた」という失敗は、私も何度か経験があります。
コミットする前であれば、変更をそのまま新しいブランチに持っていけます。
# 変更を持ったまま新しいブランチを作成する
git switch -c feature-correct-branch
# mainブランチには変更が残っていないので、mainに戻って最新化しておく
git switch main
git pull
すでにコミットまでしてしまっていた場合も、対処は可能です。
# 新しいブランチを作り、そのコミットを持っていく
git branch feature-correct-branch
# mainだけ、そのコミット前の状態に戻す
git reset --hard HEAD^
このときgit reset --hardを使うのは、あくまでまだpushしていないローカルのmainに限定してください。
push済みのコミットに対しては、以前解説した通りrevertを使うのが安全です。
マージを取り消したい
マージ直後、まだpushしていない段階であれば、マージ前の状態に戻せます。
# 直前のマージコミットを取り消す(マージ前の状態に戻る)
git reset --hard ORIG_HEAD
ORIG_HEADは、直前の危険な操作(マージやreset)の前のコミット位置をGitが自動で覚えてくれている、いわば「ワンテンポ前のブックマーク」です。
すでにpush済みのマージを取り消したい場合は、マージコミット用のオプションを付けてrevertします。
git revert -m 1 <マージコミットのハッシュ>
リモート関連の代表的エラー
“failed to push some refs” の対処
pushしようとして、次のようなエラーに遭遇したことがある方も多いはずです。
git push origin main
! [rejected] main -> main (fetch first)
error: failed to push some refs to '...'
hint: Updates were rejected because the remote contains work that you do
hint: not have locally.
私が実際に経験したのも、このエラーです。
原因はシンプルで、リモート側に、自分のローカルにはない新しいコミットが存在している状態です。
対処法は、先にリモートの変更を取り込むことです。
# リモートの変更を取り込んでからpushする
git pull origin main
git push origin main
git pullの際にコンフリクトが起きたら、これまでの記事で解説した手順でファイルを整理し、git add・git commitしてから改めてpushしましょう。
慌ててgit push --forceで押し切ってしまうと、リモート側にあった他人の変更ごと消えてしまう危険があるので、絶対に避けてください。
認証エラー
リモートリポジトリへのアクセスで、認証関連のエラーに悩まされることもあります。
remote: Support for password authentication was removed...
fatal: Authentication failed
HTTPS接続でパスワード認証が廃止されている場合に出るエラーで、代わりにPersonal Access Token(個人アクセストークン)を使う必要があります。
このあたりのリモート・GitHub連携の詳しい設定は、次シリーズのGitHub編でじっくり扱う予定です。
まずは「認証まわりのエラーはパスワードではなく設定が原因のことが多い」と覚えておいてください。
いざというときの安全策
git reflogで消えたコミットを復元する
「resetし過ぎてコミットが消えてしまった」というときの最終手段がgit reflogです。
git reflog
a1b2c3d HEAD@{0}: reset: moving to HEAD^
d4e5f6g HEAD@{1}: commit: ログイン機能を追加
reflogは、ブランチの移動履歴をすべて記録しているGitの「操作ログ」です。
消えたように見えるコミットd4e5f6gも、実はまだGitの内部には残っており、次のコマンドで復元できます。
# 消えたはずのコミット位置に戻す
git reset --hard d4e5f6g
「もうダメだ」と思ったときほど、まずreflogを確認する習慣をつけておくと、多くの場合は救出できます。
困ったらブランチを退避してから作業する
トラブル対応中に、さらに状況を悪化させてしまうのが一番怖いパターンです。
不安な操作を試す前に、念のため今の状態をブランチとして退避しておくと安心です。
# 今の状態を、別ブランチとしてバックアップしておく
git branch backup-before-fix
これで、たとえ次の操作を失敗しても、backup-before-fixブランチにいつでも戻れます。
「危険な操作の前には退避用ブランチを切る」というのは、Gitに慣れた人ほど徹底している習慣です。
まとめ
この記事のポイント
- Gitのトラブル対応は、エラーメッセージを落ち着いて読み解くことから始まる
- コミット内容のミスは
--amend、ブランチ間違いは新ブランチへの退避で対処できる - pushが拒否されたら、まず
git pullでリモートの変更を取り込む git reflogは、resetし過ぎたときの最終的な命綱になる- 不安な操作の前には、バックアップ用ブランチを切っておくと安心
これでGit編(全15本)は完結です。
「セーブポイント」というたとえから始まり、ブランチでの実験、マージやコンフリクト、履歴操作、そしてトラブル対応まで、Gitの基本を一通り解説してきました。
次に読むべき記事
ここまでのGit編は、すべてローカルリポジトリでの操作が中心でした。
次はいよいよ、GitHubを使ったチーム開発やリモート連携について、新しいシリーズで解説していく予定です。
タグ: Git, 中級者向け, 実践Tips
