CI/CDをkatacodaで体験(初心者向け) - Part4(Undoing Changes)


CI/CD入門

このぺーじでは、katacodaと呼ばれる「ブラウザから無料で勉強用のインスタンスを起動できるWebサービス」を利用してCI/CDを実践します
内容は上記リンクに沿うので、不明点があればそちらへどうぞ

Gitのバージョン管理について - Scenario4 - Undoing Changes

ここでは、CI/CDとして欠かせないGitによるバージョン管理について学習します
このシナリオで学習することをさっと確認する場合は概要を確認
理解に間違い等がございましたら、ぜひご指摘ください

概要

  • git checkoutでワーキングディレクトリの状態を前回コミット時(変更前)に戻す
  • git resetでステージングの状態をワーキングディレクトリの状態(git addする前)に戻す
  • git reset時にオプションとして--hardを利用することで、ステージングの状態(git checkout+git reset(オプションなし))を前回コミット時に戻す
  • git revertで、前回あるいは、複数回前のコミット状態に戻す
  • どのbranchに対して戻すのかcommit hash(基本的にはHEAD)を指定したほうが間違いが少ない

Step 1 - Git Checkout

git checkoutはbranchの変更時に利用されるコマンドだが、編集中のワーキングディレクトリを前回コミット時の状態に戻すことも可能
状態が戻ったことは、git statusで確認可能

$ ls -a
.  ..  committed.txt  .git  staging.txt
$ git branch
* ESC[32mmasterESC[m
$ git status
On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        modified:   staging.txt

no changes added to commit (use "git add" and/or "git commit -a")
$ git checkout .
$ ls -a
.  ..  committed.txt  .git  staging.txt
$ git branch
* ESC[32mmasterESC[m
$ git status
On branch master
nothing to commit, working tree clean

Step 2 - Git Reset

Step1では、ワーキングディレクトリ上にファイルがある状態->前回コミット時の状態に戻す操作
Step2では、ステージング上にファイルがある状態->ワーキングディレクトリ上にファイルがある状態へと戻す操作
git reset <file/directory>で、実行可能

$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

        modified:   staging.txt

$ git branch -a
* ESC[32mmasterESC[m
$ git reset HEAD .
Unstaged changes after reset:
M       staging.txt
$ git status
On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        modified:   staging.txt

no changes added to commit (use "git add" and/or "git commit -a")

HEAD とは
HEADとは端的に言うと、「現在、作業しているブランチのバージョンを指定するもの」
そのため、下記ソースコードのようにgit reset HEAD .のように記述しなくても今回は問題ありません

$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

        modified:   staging.txt

$ git reset .
Unstaged changes after reset:
M       staging.txt
$ git status
On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        modified:   staging.txt

no changes added to commit (use "git add" and/or "git commit -a")

では、なぜHEADが必要か?
作業しているbranchと異なるbranchに対して、何らかの操作を加えたり、以前のバージョンに対して操作を加える際にcommit hashを指定する必要があります
作業しているbranchが最新のバージョンであれば、commit hashHEADを利用し、そうでないなら、適切なcommit hashを選択
詳しくはこちら

Step 3 - Git Reset Hard

step3では、step1,2の操作を一度に行う
それを確かめるため、staging.txtはステージング上に、commited.txtはワーキングディレクトリ上に存在させる
その後、git reset --hardによって二つのファイルを前回コミット時へ戻す

$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

        modified:   staging.txt

$ cat committed.txt
Committed File
$ echo 'test' >> committed.txt
$ cat committed.txt
Committed File
test
$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

        modified:   staging.txt

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        modified:   committed.txt

$ git reset --hard HEAD
HEAD is now at 5d62819 New File
$ git status
On branch master
nothing to commit, working tree clean
$ cat committed.txt
Committed File

Step 4 - Git Revert

続いて学習するのはgit revert
これは、誤ってコミットした場合に利用
commit_v0(前回の状態) -> commit_v1(間違い) -> git revert (HEAD) -> commit_v0(前回の状態)
git revertはオプションとして、コメント(git commit -mで用いるコミットメントコメント)を付与したりしなかったりできる
ログを残すことで後々確認しやすいので、オプションとして-e/--editを用いる方が良い

その他のオプション
-e/--edit : コミットコメント書き込み
--no-edit : コミットコメントなし(前回のコミットコメント利用)
-n/--no-commit : コミットの取り消し(ステージングへの巻き戻し)
参考リンク

$ git log
ESC[33mcommit 676354469da2eff5cf7df1df0f17ba8183ce5bbeESC[mESC[33m (ESC[mESC[1;36mHEAD -> ESC[mESC[
Author: Katacoda Scenario <[email protected]>
Date:   Wed Oct 14 00:03:04 2020 +0000

    Commit To Revert

$ git revert HEAD -e   //"-e"オプションでeditorが表示される。適当なコメントを入力
[master 3240f2b] Revert "Commit To Test Revert"
 1 file changed, 1 insertion(+), 1 deletion(-)
$ git log
ESC[33mcommit 3240f2b8b0a87363ed07fac7ade4a4c267e52bbdESC[mESC[33m (ESC[mESC[1;36mHEAD -> ESC[mESC[
Author: Katacoda Scenario <[email protected]>
Date:   Wed Oct 14 00:06:56 2020 +0000

    Revert "Commit To Test Revert"

    This reverts commit 676354469da2eff5cf7df1df0f17ba8183ce5bbe.

ESC[33mcommit 676354469da2eff5cf7df1df0f17ba8183ce5bbeESC[m
Author: Katacoda Scenario <[email protected]>
Date:   Wed Oct 14 00:03:04 2020 +0000

    Commit To Revert

上の結果から分かる通り、logには新しく"Commit To Test Revert"と表示されている

注意
git revertはステージングやワーキングディレクトリに対しては、何も操作しない

$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

        modified:   index.txt

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        modified:   working.txt

$ git revert HEAD --no-edit
error: your local changes would be overwritten by revert.   //commitされていない修正のため、エラー
hint: commit your changes or stash them to proceed.
fatal: revert failed

Step 5 - Git Revert

step4では、一つ前のコミットに戻していたが、二回以上前のコミットに戻すことも可能
現在の状態からいくつ前に戻るかはgit revert HEAD...HEAD~(n)のように指定

$ cat test.txt
test
2
3
4
$ gi add test.txt
bash: gi: command not found
$ git add test.txt
$ git commit -m 'fours commit'
[master c3d82f1] fours commit
 1 file changed, 1 insertion(+)
$ git log --oneline
ESC[33mc3d82f1ESC[mESC[33m (ESC[mESC[1;36mHEAD -> ESC[mESC[1;32mmasterESC[mESC[33m)ESC[m fours commit
ESC[33m909ad91ESC[m third commit
ESC[33m1cb550cESC[m second commit
ESC[33m0062e56ESC[m first commit
ESC[33m1d059eaESC[m Revert "Commit To Revert"
ESC[33m12fcca9ESC[m Revert "Revert "Commit To Revert""
ESC[33md5aa2f3ESC[m Revert "Commit To Revert"
ESC[33m3d950a6ESC[m Commit To Revert
ESC[33m88e2869ESC[m New File
ESC[33m43250bfESC[m Fixing Error
ESC[33m22457e2ESC[m First Commit
$ git revert HEAD...HEAD~2
[master 7dec1c4] Revert "fifth commit"
 1 file changed, 1 deletion(-)
[master 05804a9] Revert "third commit"
 1 file changed, 1 deletion(-)
$ git log --oneline
ESC[33m05804a9ESC[mESC[33m (ESC[mESC[1;36mHEAD -> ESC[mESC[1;32mmasterESC[mESC[33m)ESC[m Revert "third
ESC[33m7dec1c4ESC[m Revert "fifth commit"
ESC[33mc3d82f1ESC[m fours commit
ESC[33m909ad91ESC[m third commit
ESC[33m1cb550cESC[m second commit
ESC[33m0062e56ESC[m first commit
ESC[33m1d059eaESC[m Revert "Commit To Revert"
ESC[33m12fcca9ESC[m Revert "Revert "Commit To Revert""
ESC[33md5aa2f3ESC[m Revert "Commit To Revert"
ESC[33m3d950a6ESC[m Commit To Revert
ESC[33m88e2869ESC[m New File
ESC[33m43250bfESC[m Fixing Error
ESC[33m22457e2ESC[m First Commit
$ cat test.txt
test
2

上記の結果の通り(分かりやすさのため、katacodaと異なる手順で確認してます)、test.txtは一行ずつコミットを行い、4回目のコミット後にgit revertとして5回目のコミットを実行
結果、二つ前の状態に遷移