17
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

リンクアンドモチベーションAdvent Calendar 2024

Day 2

GitHubでコミットを取り消す方法【図解で簡単解説】

Last updated at Posted at 2024-12-01

はじめに

こんにちは!リンクアンドモチベーションの宮田です!

本記事はリンクアンドモチベーション Advent Calendar 2024の2日目を担当しています。🎄

アドベントカレンダー初参戦ということでワクワクしながら書きましたが、至らない点もあるかと思います。精一杯書きましたので、どうぞ最後までお付き合いください!


4月に入社してからエンジニアとしての道を歩み始め、手厚い研修を経ました。とはいえ、まだまだわからないことだらけです。特に、GitやGitHubに関しては、

以前、記事を書いて、「わかったつもり」だったのに、初めて自分でチケットを実装し、プルリクエストを出す段階で壁にぶつかりました。

先輩「このコミットは別のPRで出してほしい!」

僕(別PRか。プッシュしちゃったけどどうしよう??(´・ω・))


どう操作すればいいのかわからず、戸惑ってしまいました。これをきっかけに、自分の知識の足りなさに改めて気づかされました。

そこで今回は、

  1. GitとGitHubの基本を復習
  2. VScodeでのGit操作がGitHub画面にどう反映されるかを確認
  3. GitHubにプッシュしたコミットを取り消す方法とその種類を解説

という3本立て(+α)で、僕自身の学びを共有していきます!

image.png

コミットの取り消し操作自体はそんな頻繁に行うものではないかもしれませんが、GitやGitHubについての理解を深める大変良い機会になりました!

この記事が、同じような悩みを持つ方の助けになり、「GitHub、なんかよくわからん……」という感覚を少しでも和らげられるきっかけになれば嬉しいです。

それでは、GitHubと仲良くなれるように頑張っていきましょう!!🐈🙌

目次

  1. はじめに
  2. GitとGitHubの基本を復習
  3. VScodeでのGit操作がGitHub画面にどう反映されるかを確認
  4. GitHubにプッシュしたコミットを取り消す方法とその種類を解説
  5. チェリーピックという方法🍒
  6. 最後に
  7. 参考文献

GitとGitHubの基本を復習

復習といってもかなり簡単な説明になります

Git
Gitはソースコードの変更履歴を管理するためのバージョン管理システムです。コードの変更を記録して、過去のバージョンに戻したり、複数人が並行して作業する際の変更内容を統合したりすることができます。Gitはローカルで使用でき、個人での作業にも対応しています


GitHub
GitHubは、Gitを利用したリモートリポジトリサービスの一つです。Gitのローカルリポジトリは自分のPCにしか存在しませんが、GitHubを使うことで、インターネット上にリモートリポジトリを作成し、複数の開発者が同じプロジェクトで作業できるようになります。チームで開発を行う際に、各開発者が自分のPCでコードを編集した後、GitHubに変更をプッシュ(push) することで、全員が同じコードを共有できるようになります。

以下、自分で作成したお手製GitHub図解です。

image.png

ローカルリポジトリとリモートリポジトリとの間でやり取りを表したのが以下の図です。

image.png

別のローカルリポジトリもいるパターンです。
結局図で理解するのが一番良さそうです。

image.png

VScodeでのGit操作がGitHub画面にどう反映されるかを確認

今回は説明用にGitGitリポジトリを作ってみました。
GitHubで確認できるのはもちろん、リモートリポジトリです。

ブランチを切って、VScodeからpushすると、GitHub上にPR(Pull Request)が作成されます。今回はわかりやすいように「PUSH」というコミットメッセージにしてあります。

image.png

このPRをクリックすると、ConversationやCommitsでこのブランチからのコミット履歴が確認できます。(※コメントが雑なのは許してください)

image.png

コミット履歴といっても今は一つしかなく、わかりにくいと思うので、一度PRを作成したブランチから、追加で変更を加えてcommitpushしてみます。
次のコミットメッセージはとりあえず「CHANGE」にしてみました。すると、以下の画面のように新規のコミットが追加されます。

image.png

一つのブランチからのcommitpushは一つのPRにまとめられます。

では、試しにもう一つ別のブランチ(Branch b)を作ってそこからPRを作成してみます。
すると、以下の画面のようになります。
(わかりやすいようにPR名を編集してあります)

image.png

最初に作成したブランチと今回作成したブランチで別のPRになっています。

PRはブランチ単位で作成される

GitHubにプッシュしたコミットを取り消す方法とその種類を解説

それでは本題です。プッシュ済みのコミットをどうやったらGitHub上から取り消すことが出来るのか。

取り消し方は2種類あります。

  1. 強制プッシュ
  2. 新しいコミットで取り消す

順番に説明していきます。

1. 強制プッシュ

まずは強制プッシュから説明します。今回僕が実際に使用した方法です。

ローカルリポジトリの状態が遅れている時、通常はプルをして、リモートリポジトリの最新の状態を取り込んでからでないとプッシュできません。
ただ、他のメンバーがまだプルをしていない状態や、1人で使っているリポジトリなどで、間違えてプッシュをした内容を書き換えても問題がない場合に、強制プッシュという方法があります。

では説明していきます。まずはGitHubの画面を確認してみましょう。
Commitsにそのブランチでプッシュされたコミットが古い順にならんでいます。
image.png

例えば、取り消したいコミットがあったとして、まずは、コマンドライン上で、コミットをリセット(なかったことに) します。

git reset HEAD^           #HEAD^は直近のコミットを指す

上のコマンドを使用しコマンドライン上でリセットすると、ローカルリポジトリでそのコミットがなかったことになります。 

下の図のようなイメージです。

image.png

見てわかるように、リモートリポジトリとの間に差(履歴が遅れている状態)が生まれることになります。(まだこの段階ではローカルリポジトリでリセットした状態はリモートリポジトリには反映されません。)

pushローカルリポジトリの変更をリモートリポジトリへ反映させる(履歴を進める)コマンドなので、
image.png

git pushすると、

git push       

To https://github.com/ShoyaMiyata/GitGit.git

 ! [rejected]        branchA -> branchA (non-fast-forward)
error: failed to push some refs to 'https://github.com/ShoyaMiyata/GitGit.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. If you want to integrate the remote changes,
hint: use 'git pull' before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.

リモートリポジトリの状態よりも遅れてるから、まずはリモートリポジトリの状態を受け入れてちょうだい」となるわけです。でも今回はローカルリポジトリで意図的にコミットを取り消して作った状況であり、リモートリポジトリにも反映させたいので、

git push -f  

git push-f(--force)オプションを付けることで強制的にリモートリポジトリに変更を反映させることができます。

つまり、「うっせぇだまれです。黙って従うです。」 ということができます。

image.png

実際に実行して確認してみると、

image.png

晴れて、プッシュしたコミットを取り消すことができました。
今回はあくまでPR段階で、まだ誰にもプルされていない状態だったので強制プッシュで問題なく対応できました。

他の開発者と協力して作業している場合、その影響をしっかり理解してから行うことが大事になります。

2. 新しいコミットで取り消す

先ほどの強制プッシュとは異なり、今度は新しいコミットで前のコミットをなかったことにする方法です。

今回使うのが git revert というコマンドです。

強制プッシュで使用したgit reset は指定したコミットまで戻すことで、作業をリセットしましたが、今回のgit revert既存のコミットを取り消す新しいコミットを作成することで、履歴を安全に修正できます。

①直近のコミットを取り消す場合は

git revert HEAD^

②遡って取り消したい場合は、git logでコミットログを確認して、なかったことにしたいコミットのハッシュを取得して、

git log

commit 573eff4904eefc0177cdbcda1ffcf3a6266addbf  # 例
Author: Shoya Miyata
Date:   Sat Nov 30 11:10:29 2024 +0900
git revert 573eff4904eefc0177cdbcda1ffcf3a6266addbf

します。その状態で

git push

すると、GitHubの画面上では

image.png

頭にRevertと付いたコミットが追加で作成されています。
これならば、リモートリポジトリの履歴を保持できるので、他の人が前のコミットをプルしていた場合でも、Revertコミットをプルしてもらうことでミスを修正できます。

プッシュ済みのコミットの取り消し方

  • ミスって不要なコミットしちゃったから消したい💦
    • 強制プッシュ
  • この前出したコミットやっぱなしってことにしたいな。やっぱりあれなしで🙇
    • Revertコミット

こんなイメージで使い分けが出来そうです。

一応今回は、別PRとして改めてコミットを出しなおすために、強制プッシュでコミットを取り消し、別のブランチで再度コミットをプッシュすることで対応できました。(もっとスマートな方法あればぜひ教えてください!)

チェリーピックという方法🍒

先ほど別PRを出すために、コミットを取り消してから、再度同じ内容をプッシュするという方法を取りましたが、
チェリーピックという方法を使えば、特定のコミットを選んで現在のブランチに適用することができます。 この「チェリーピック (cherry-pick)」という言葉は、さくらんぼ狩りのように、自分が欲しいものだけを選び取る行為から由来しているそうです🍒

たとえば、BranchAのコミットを別PRとして出したいとします。

image.png

今回はBranchCで受け入れていきましょう。

image.png

そしたら、ターミナル上でBranchCに移動してgit log --allします。

git log --all

--allオプションを付けることで、現在チェックアウトしていないブランチのコミット履歴も表示できます。(通常は現在のブランチのログのみが表示される)

 git log --all
 
commit 295fa2b3737094248028ee4176940d1ba58d9ffb (refs/stash)
Merge: 7067c60 01a1306
Author: Shoya Miyata 
Date:   Sun Dec 1 14:17:57 2024 +0900

    WIP on branchc: 7067c60 クラス作成

commit c200db35fe319da09bb657dc34774fb33cfc2347 (branch-A)
Author: Shoya Miyata 
Date:   Sat Nov 30 20:29:23 2024 +0900

    別PRで出して

対象のログを確認できたので、git cherry-pickをしていきましょう。

git cherry-pick <適用したいコミットのハッシュ>

git cherry-pick c200db35fe319da09bb657dc34774fb33cfc234 # 今回はこのハッシュ

問題なくコミットを受け入れることが出来たら、git pushをします。
BranchCを確認してみると、

image.png

無事にBranchAのコミットをBranchCに反映させられました。
この時、もともとのBranchAにはコミットが残っています。(必要ない場合は先ほど解説した強制プッシュを使うなどして、取り消す対応が必要です。)

今回はミスのコミットを別PRへ移すためにcherry-pickを使いましたが、他のブランチのコミットを一部反映させたいというときにも使えそうです。

ブランチ移動の際にエラーが発生して困った場合は、こちらの記事もぜひご覧ください。

最後に

調べてインプットしたことを記事としてまとめる作業はかなり骨が折れますが、何度も、何度も自分で読み返して、間違いがないかを確認したり、どうやって構成したら伝わりやすいかを考え続けるうちに、最初は「わからない」がきっかけで調べ始めたことも気づけば、「自分のもの」になった感覚があります。

良質なインプットのためのアウトプット
良質なアウトプットのためのインプット

このサイクルをこれからも続けていきたいです!
最後までお読みいただきありがとうございました!

参考文献

図解! Git & GitHubのツボとコツがゼッタイにわかる本[第2版]

はじめてでもできる GitとGitHubの教科書

17
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
17
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?