【初心者必読】リポジトリを壊すGitの危険コマンド一覧

先日gitの主要コマンドについてご紹介しました。
ぜひgitを今まで触ってこられなかった方には、主要コマンドリストを見ながらガンガンgitに触れていただきたいと思いますが、
実はgitの中には、『危険なコマンド』があることはご存知でしたか?

もちろん『危険なコマンド』と言っても、gitに正式実装されているものなので、悪意あるコードではないのですが、
しかし『使い方を間違えると、プロジェクトに損害を与えてしまう』コマンドも存在しているのです。

今日はそんな『使わない方がいいコマンド』、『使うとしても気をつけるべきコマンド』をご紹介します。

目次

git push -f

コマンド説明:
『git push -f』は、プッシュ時にエラーや注意が出ていたとしても、問答無用でプッシュするコマンドです。

gitがプッシュ時に何らかのエラーを出した場合は、自分のローカル環境とgitリポジトリに何らかの無視できない差異が存在するはずなので、その原因を理解した上で利用してください。
もし無視して実行してしまうと、チームメンバーのコミットが上書きされて消える、デグレが発生するなどの問題につながる可能性があります。

代替案として、より安全な–force-with-leaseを利用するのであれば、多少リスクが低減されます。
(ローカル側が最新でないとプッシュできない制限付きのforceです)

git rm -r

コマンド説明:
git rm』は.gitignore前に既にコミットしてしまった設定ファイルなどを、git上から削除する際によく利用するコマンドです。
しかしながら『–cached』をつけずに実行した場合、作業コピーごとファイルが削除されてしまいます。

特に『git rm -r .』のように全ファイルに適用した場合は、文字通り全ファイルが削除されてしまいます。作業中の内容を消さないように慎重に対応しましょう。

git rebase

コマンド説明:
このコマンドも、ある程度利用頻度が高いコマンドです。実際『利用している』『利用しているのを見たことがある』人も多いでしょう。

こちらはコミットの書き換えができるコマンドとなります。このコマンドを使うと、あるブランチの変更を別のブランチの最新状態に「再適用(rebase)」することができるのです。

例えばgitの管理者から『コミットを汚したくない』という要望が出た際、
『プルリクエスト前のコミットをひとまとめにしてプッシュする』といったケースで使用することがあります。

filter-branchと違って、対象範囲を絞ることができるため、大惨事には繋がりにくいです。
ただし、履歴の書き換えを行っていることには変わりないため、細心の注意を払って使用しましょう。

git reset –hard

コマンド説明:
コマンドのラストに『–hard』がついていますが、これはコミットのリセットをするgit resetの中でも、最も強いモードであるhardを適用するコマンドです。
softやmixedというモードではコミット履歴が残るのに対し、hardは履歴が残りません。
コミットされていない変更、ステージングされているがコミットされていない変更などは、完全に消去され戻すことができなくなります。

特に共有ブランチでは、他の開発者が持つ履歴と矛盾が生じてしまうこともあるため、使用をなるだけ避けてください。

git filter-branch

コマンド説明:
『git filter-branch』は、ターミナル上から書き換えやフィルタリングを行うことができるコマンドです。
それだけ聞くと至って汎用性の高いコマンドのように思えるかもしれませんが、『git filter-branch』が危険なのは『すべてのコミットに対して書き換え・フィルタリングを行うことができる』点です。

gitの良い点は『すべての変更履歴が残る』ことですが、この『git filter-branch』は、その変更履歴ごと書き換えたり、削除したり、といったことが可能なのです。
事実上git履歴が抹消されることになるため、やむにやまれぬ事情がある場合を除き利用は推奨しません。
例えば『外部に漏らしてはいけない情報(秘密鍵・env情報)が掲載されていた』『非常に誤解を招くような誤ったメッセージがコミットメッセージに入っていた』というケースです。

なお例えこのコマンドを使わなければいけなくなったとしても、
予めgitのバックアップを保存しておき、正常な処理が行われたことを確認してから、バックアップを削除する、という手順を踏みましょう。

git submodule

コマンド説明:
『git submodule』とは、gitリポジトリに外部のリポジトリをサブモジュールとして登録する機能です。

……それだけ聞くと、特に問題のない、便利な機能のように思えるかもしれません。
しかし、別で開発を進めているであろう外部のリポジトリが加わることで管理が煩雑になる、混乱するリスクがあります。

起きうる問題:

『git submodule』で追加されたサブモジュールは、本体のプロジェクトとは別のリポジトリ(プロジェクトフォルダ)として存在する形となります。
なのでコミット履歴等も親側から確認するのではなく、そのサブモジュール自身のコミット履歴を見る必要が生じます。

その仕様をよく把握しないまま、『サブモジュール側の差分を親側でプッシュ』してしまうと、『サブモジュール側のリポジトリには存在しないコミット』が生まれてしまうのです

更に恐ろしい問題が起きることがあります。それは『更新の多いリポジトリをサブモジュールにした場合』です。

サブモジュールに更新がかかった場合、その更新は当初サブモジュール自体のリポジトリ内にしか反映されません。
この更新を親プロジェクトに反映させるためには、親プロジェクトの開発者が、サブモジュールの新しいコミットIDを親プロジェクトに組み込む必要が生じます。

問題は、この組み込み作業が完了する前にサブモジュールで「追加の更新」が行われた場合です。
この「追加の更新」は、先に処理された組み込み作業には含まれていません。その結果、親プロジェクトには古いコミットIDのサブモジュールが反映され、最新の変更が取り込まれていない状態になる可能性があります。

このような場合、別々のコミットIDを持つサブモジュールが2つ存在することになるのです。
しかも、どちらが最新の状態を反映しているのか、判断するのが難しくなります。2つのサブモジュールにはぱっと見コミットIDの違いしかないからです。

もしこのような事態がプロジェクトのリリース直前、プルリクエストラッシュ時に起きた場合、大きな混乱を招くことでしょう。

『git submodule』は、すべてのリスクを理解した上で、すでに安定しきったライブラリ等を使う場合のみ、利用することとしましょう。

『危険なコマンドの概要』を知っておこう

以上、『gitの危険なコマンド』をご紹介して来ましたが、もしあなたがこれから頻繁にgitを触るのであれば、ぜひ『危険なコマンド』だけでなく『なぜ危険なのか』『どういうときに使うのか』といった点も覚えておくことをおすすめします。

リスクがあるとしても『git rebase』等はよく使われるコマンドですし、『git submodule』や『git filter-branch』等も、時と場合によっては使う必要に迫られることがあるでしょう。
これらのコマンドは『ただただ危険』なわけではなく、『必要なケースが存在する』からこそ実装されているのです。
しかもそれは、リリースの直前だったり、重大なトラブルが起きた時だったりします。

ぜひこれからいろんなgitコマンドに触れていただき、『仕事が早い』『危険なことをしない』そして『トラブルの対処に強い』、そんなエンジニアを目指してみてください。

お問合せ&各種リンク

presented by 

  • システム開発、アプリ開発
  • マッチングアプリ開発
  • インフラ構築支援等、なんでもご相談ください。
よかったらシェアしてね!
  • URLをコピーしました!
目次