ソフトとかYoutubeとか

ソフトウェアとかyoutubeに関して調べたことを書いていきます。

Gitで困ったときにみるコマンド集

概要

2022 年に 低レイヤを知りたい人のための C コンパイラ作成入門 をやった時、Git 操作で苦労したのでここにまとめておきます。

通常の処理: git push, add, commit, push

通常の作業手順

  1. プロジェクトフォルダ直下にcd project_dirなどで移動。
  2. ローカルリポジトリに前の作業状態を引っ張ってくる(下記コマンド)。
  3. コーディングを行う。
  4. ステージングしてコミット(下記コマンド)。
  5. commit の内容確認後、リモートリポジトリにアップロード

使うコマンドは以下。

cd project_dir
git pull               # ダウンロードみたいなもん

# -- このタイミングでコーディング作業をする。 --

git add file1 file2 .. # ステージング
git commit -m "commentをここに書く"
git log -p             # コミットの内容を確認
git push               # アップロードみたいなもん

git commit -mのところを単にgit commitとすると、エディタが開くのでそこにコメントを書く。

直前の commit を取り消す(ローカルファイルの状態はそのまま): git reset --soft

前の commit を強制消去するので一人リポジトリの利用に留める。

git reset --soft HEAD^ # HEADの一個前に戻る
git push -f origin master # リモートリポジトリに強制上書き!!!

reset --soft は commit のみを取り消すコマンド。
(reset --hard は commit とそれに伴うファイル状態も戻す。)

git reflog : git reset を取り消したい、最新の commit に戻したい

git reflog を使えばコマンド履歴を取得できる。 戻りたい地点のラベルを調べることができる。
例えば git reset --soft HEAD^ した後は以下のようになる。

git reflog

reflog の結果 ↓

e395361 (origin/master) HEAD@{0}: reset: moving to HEAD^
5172683 (origin/master) HEAD@{1}: commit: sort codes
e395361 (HEAD -> master) HEAD@{2}: commit: 事前設定ヘッダファイル9cc_config.hをコンパイラから直接呼び出すように変更
9cc9660 HEAD@{3}: commit: volatile, const を読み飛ばすように変更
4c844e4 HEAD@{4}: commit: ヘッダファイル整理 (#include完了に際し)

上の行が直近のコマンド操作を表す。 ここで、1 行目と 3 行目の行頭が両方e395361と同一の ID(?)なっている。 これは、1 行目の reset 操作で 3 行目の commit の状態に戻ったことを表している。 最新の commit は 2 行目だから、ここに戻りたい場合は、HEAD@{1}に reset すればよい。

git reset --soft HEAD@{1}

直前の commit とファイル変更を取り消す: git reset --hard (使用頻度低)

git reset --hard HEAD^ # 1 つ前に戻る
git reset --hard HEAD^^ # 2 つ前に戻る
git reset --hard HEAD~3 # 3 つ前に戻る
git push -f origin master

直前の commit を修正: git revert

reset と異なりコミット内容を取り消した履歴が残る。 commit コマンドのような感覚で使える。

# 先に修正作業を行う。
git revert HEAD # HEAD(通常は最新commit)を取り消してcommit
# エディタが開きコメントを要求される。
git push

変更を一時的に退避: git stash

作業の途中で別に優先される修正が入った時に使う。後で戻せる。

git stash
# コメントを書く 一時退避した内容について
git stash list # 退避名の一覧表示
stash@{0}: On master: グローバル変数実装途中
git stash list -p # 退避差分の確認
git stash apply stash@{0} # 退避した stash@{0} を取り戻す(適用)

apply 後に 衝突(conflict) が発生する場合がある。 衝突が発生しなかったファイルは stage された状態になっている。 衝突が発生したファイルは stage されておらず、その内容が表示される。 (vscode ではファイル名横の状態を示す部分に ! マークが表示される。)

衝突が発生した箇所は以下のように、ファイル内に <<.., ==.., >>.. の 3 行とともに apply 前後の両方の内容が書き込まれている。 手動でいらない方と <<.., ==.., >>..の 3 行を消していく。 すべて終わったら、そのファイルを stage する。 (vscode では ! マークがなくなっていることを確認。)

衝突が発生したファイル ↓

...
<<<<<<< Updated upstream
適用先の内容
=======
退避した内容
>>>>>>> Stashed changes
>>>>>>> ...

これを衝突が発生したファイルすべてについて行う。 全ファイルが stage された状態になれば OK。 しかし、git の内部状態ではまだ衝突状態なので以下を行う。

git reset # すべてunstageされる。
git diff # 衝突解消の確認
# 変更内容が表示されればOK。何も表示されなければ何か間違っている。

あとは適当なタイミングで残った stash を消すだけ。

git stash drop stash@{0} # stash@{0}を削除
# もしくは、はじめからapplyの代わりに、popを使ってもよい
git stash pop stash@{0} # apply + drop  (要調査)

手動ではなく stash の内容を全採用したいなら git checkout --theirs