GitHub プルリクエスト後に間違いに気づいたとき

1つのプルリクエストには、1つの意味だけを持たせるべきだ。

プルリクエストを作成後、今回のプルリクエストに関係のない修正が紛れ込んでいたことに気づいた。やるべきことは、ブランチを正しい状態にすること。

プルリクエストは GitHub上のリモートブランチに紐づいているので、プルリクエスト自体の修正などは必要ない。ここ、勘違いしていた。

具体的な状況

  1. img_upload ブランチを作って、画像アップロード機能を追加する1つのコミットを作った
  2. img_upload ブランチをプッシュ
  3. GitHub 上でプルリクエスト作成
  4. GitHub 上で Files changed を確認していたら、画像アップロードに関係のない修正(プルリクエストを分けるべきもの)までしていたことに気づいた

変更手順

reset --soft を使う

今回実際にやった方法。

  1. ローカルの img_upload ブランチで$ git reset --soft HEAD^して、コミット直前の状態に戻す
  2. 今回のプルリクエストに入れない部分を元に戻す
  3. 手を加えたファイルをadd
  4. コミット
  5. $ git push --force-with-lease origin img_uploadでリモートブランチを上書き

reset を使う

--softをつけなかったらこうなる。ほとんど変わらないけど。

  1. ローカルの img_upload ブランチで$ git reset HEAD^して、コミット前の状態に戻す(ステージしていない状態)
  2. 今回のプルリクエストに入れない部分を元に戻す
  3. コミットするファイル全部add
  4. コミット
  5. $ git push --force-with-lease origin img_uploadでリモートブランチを上書き

--amend を使う

Gitのドキュメントを見た感じだとこれが一番いいかもしれない。「5. $ git push --force-with-lease origin img_uploadでリモートブランチを上書き」以外の部分について練習リポジトリを作ってやってみた。

想定シーン

  1. master ブランチに hello.txtというファイル(中身は空)が1つだけある
  2. hello.txtadd して commit(initial commit)
  3. hello.txtHello!を書き込んでコミット(second commit)
  4. second commit に、新しいファイルnew.txtも入れておくべきだったと気づく
# リポジトリの初期化
$ git init

# hello.txtを作ってaddしてcommit
$ touch hello.txt
$ git add hello.txt 
$ git commit -m 'initial commit'

# hello.txtに"Hello!"を書き込んでaddしてcommit
$ echo 'Hello!' > hello.txt 
$ cat hello.txt 
Hello!
$ git add hello.txt 
$ git commit -m 'second commit'

# ここまでのログを確認
$ git log --oneline
5f2b8a6 (HEAD -> master) second commit
30ad88e initial commit

# second commitに入れておくべきだったファイルを作ってadd
$ touch new.txt
$ git add new.txt 

# commitのやり直し
$ git commit --amend
# コミットメッセージを入力するためエディタが立ち上がる
#(やり直すコミットのメッセージが入力されている)=> 保存

# hello.txtへの修正が反映されているか確認
$ cat hello.txt 
Hello!

# ログ確認(second commitのハッシュは変わる)
$ git log --oneline
7512bf9 (HEAD -> master) second commit
30ad88e initial commit

Git - 歴史の書き換え

フォースプッシュ

あるブランチですでにプッシュしたコミットがあると、それを取り消したりして矛盾があるプッシュは受け付けてもらえない。そこで必要となるのが、フォースプッシュ(強制プッシュ)。

$ git push -f origin branch_name
$ git push --force origin branch_name

フォースプッシュは強制的にリモートリポジトリを上書きするため、かなり注意して使う必要がある。チーム開発では以下のようにすることが多い。

$ git push --force-with-lease origin branch_name

--force-with-leaseオプションをつけておけば、自分が最後にプッシュした後にリモートブランチに変更があるとプッシュができない。他の人の変更履歴を意図せず消してしまう事態を防げる。

Git - git-push Documentation