#前の記事はこちら
GitとGit Hub 入門(1/3)
GitとGit Hub 入門(2/3)
こんな時どうする?
仕事中によくあるシーンをまとめたので、一緒に練習してみましょう。
ステージングへの追加を取り消す
勢い余ってステージングにファイルを追加してしまったけど、次のコミットにはやっぱり含めたくない!という場合です。
試しに、ファイル「test2」をステージングに追加します。
$ git add test2
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: test2
答えが表示されていますね。
(use "git reset HEAD <file>..." to unstage)
案内の通りに、ステージングからtest2を元に戻します。
$ git reset HEAD test2
$ git status
On branch master
Untracked files:
(use "git add <file>..." to include in what will be committed)
test2
nothing added to commit but untracked files present (use "git add" to track)
ステージングに追加する前に元に戻りましたね。
ここで、新しい言葉が出てきました。HEAD
って何でしょう。
HEADとは
HEADは、今作業しているブランチの最新のコミットのことです。
git log
でコミットログを確認してみましょう。
$ git log
commit 7022b44cb174e7d1d932a950d052fcdec9b36408 (HEAD -> master, origin/master)
Author: hoge <53826023+hoge@users.noreply.github.com>
Date: Sat Oct 12 22:15:23 2019 +0900
Create README.md
commit f733bfe11003832f28f4803481cbe086e1903e4a
Author: hoge <hoge@gmail.com>
Date: Sat Oct 12 19:13:31 2019 +0900
first commit
今、HEADは一番上のREADMEを追加した時のコミットになっています。
git show HEAD
で最新のコミットの内容を見ることができます。
$ git show HEAD
commit 7022b44cb174e7d1d932a950d052fcdec9b36408 (HEAD -> master, origin/master)
Author: hoge <53826023+hoge@users.noreply.github.com>
Date: Sat Oct 12 22:15:23 2019 +0900
Create README.md
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..bab6eaf
--- /dev/null
+++ b/README.md
@@ -0,0 +1,2 @@
+# sample
+sample for remote repository
ついでに、最新のコミットの1つ前のコミットはHEAD^
になります。
前のコミットになるほど、^
が増えていきます。
最新のコミットの1つ前のコミットは一番最初のコミットになりますね。
$ git show HEAD^
commit f733bfe11003832f28f4803481cbe086e1903e4a
Author: hoge <hoge@gmail.com>
Date: Sat Oct 12 19:13:31 2019 +0900
first commit
diff --git a/test1 b/test1
new file mode 100644
index 0000000..e69de29
つまり、git reset HEAD test2
はHEADの状態
まで元に戻す、ということになります。
commit の後にある f733bfe11003832f28f4803481cbe086e1903e4a
はコミットIDで、HEADの代わりにこれを入力しても同じになります。
コミットした時のコメントを修正する
直前のコミット
のコメントを修正したい場合です。
まず、ファイル「test2」をステージングに追加し、コミットまで行いましょう。
コメントは"add hoge"
にします。
$ git add test2
$ git commit -m "add hoge"
[master c26d97e] add hoge
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 test2
git log
でコミットされたことを確認します。
$ git log
commit c26d97e9a6c9460a0b9790f3040b12beca1750f0 (HEAD -> master)
Author: hoge <hoge@gmail.com>
Date: Sun Oct 13 15:11:59 2019 +0900
add hoge
コメントを"add test2"
に修正します。
$ git commit --amend -m "add test2"
コミットログのコメントが修正されていることを確認しましょう。
$ git log
commit 255795fc007dc6c5e64cc4acd2a54ca1e62f64c4 (HEAD -> master)
Author: hoge <hoge@gmail.com>
Date: Sun Oct 13 15:11:59 2019 +0900
add test2
コメントが修正できましたね。
コミットを取り消す
間違えてコミットしてしまったけど、変更箇所が漏れてた時など、コミットを無かったことにしたい場合です。
これも、git reset
を使います。
$ git reset --soft HEAD^
HEAD^
は、最新のコミットの1つ前を指しますから、最新のコミットの1つ前まで戻す、という意味です。
--soft
をつけると、コミットの操作のみが取り消されて、ステージングに追加された状態まで戻ります。
コミットログを見てみましょう。
先ほどの、add test2
のコミットがなくなりましたね。
$ git log
commit 7022b44cb174e7d1d932a950d052fcdec9b36408 (HEAD -> master, origin/master)
Author: hoge <53826023+hoge@users.noreply.github.com>
Date: Sat Oct 12 22:15:23 2019 +0900
Create README.md
commit f733bfe11003832f28f4803481cbe086e1903e4a
Author: hoge <hoge@gmail.com>
Date: Sat Oct 12 19:13:31 2019 +0900
first commit
git status
でステージングの状態を見てみましょう。
test2のファイルが追加されていますね。
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: test2
ちなみに、--soft
を付けないと、ステージングに追加した操作も一緒に取り消されます。
また、--hard
とすると、作業中のファイルの状態もHEAD^
の状態(最新のコミットの1つ前の状態)になります。つまり、test2のファイルが削除されます。(気をつけて。。)
プッシュしたファイルを元に戻す
間違えてプッシュしちゃった・・・という時プッシュを取り消すことができます。
この作業は複数人で同じリモートリポジトリを見ながら作業している場合、少し危険です。ちゃんとプッシュを取り消すことを周知しておきましょう。
無かったことにする
まず、ファイル「test2」をコミットし、リモートリポジトリにプッシュします。
$ git commit -m "add test2"
[master 72225df] add test2
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 test2
$ git push origin master
Enumerating objects: 3, done.
Counting objects: 100% (3/3), done.
Delta compression using up to 4 threads
Compressing objects: 100% (2/2), done.
Writing objects: 100% (2/2), 264 bytes | 264.00 KiB/s, done.
Total 2 (delta 0), reused 0 (delta 0)
To https://github.com/hoge/sample.git
7022b44..72225df master -> master
コミットログも追加されていますね。
$ git log
commit 72225dfff26c3e09114614739f584b5b6c9701af (HEAD -> master, origin/master)
Author: hoge <hoge@gmail.com>
Date: Sun Oct 13 16:54:55 2019 +0900
add test2
commit 7022b44cb174e7d1d932a950d052fcdec9b36408
Author: hoge <53826023+hoge@users.noreply.github.com>
Date: Sat Oct 12 22:15:23 2019 +0900
Create README.md
commit f733bfe11003832f28f4803481cbe086e1903e4a
Author: hoge <hoge@gmail.com>
Date: Sat Oct 12 19:13:31 2019 +0900
first commit
まず、先ほど説明した方法でコミットを取り消します。
$ git reset --soft HEAD^
$ git log
commit 7022b44cb174e7d1d932a950d052fcdec9b36408 (HEAD -> master)
Author: hoge <53826023+hoge@users.noreply.github.com>
Date: Sat Oct 12 22:15:23 2019 +0900
Create README.md
commit f733bfe11003832f28f4803481cbe086e1903e4a
Author: hoge <hoge@gmail.com>
Date: Sat Oct 12 19:13:31 2019 +0900
first commit
add test2
のコミットが消えましたね。
この状態で、プッシュし直します。
$ git push origin mastser
error: src refspec mastser does not match any.
error: failed to push some refs to 'https://github.com/hoge/sample.git'
おっと、エラーになりましたね。
リモートリポジトリで記録されたコミットログと、プッシュされたコミットログに乖離があったからです。
具体的には、リモートリポジトリにはadd test2
というログがまだ残っているのに、新たにプッシュされたコミットログにはadd test2
が無くなっているからです。
あまりお行儀はよくありませんが、-f
を付けて強制的にプッシュします。
$ git push -f origin master
Total 0 (delta 0), reused 0 (delta 0)
To https://github.com/hoge/sample.git
+ 72225df...7022b44 master -> master (forced update)
エラーが出ず、プッシュできましたね。
コンフリクトを修正する
リモートリポジトリとローカルリポジトリで同じところに更新が入った場合、ローカルリポジトリからリモートリポジトリにプッシュするとエラーが出てプッシュできません。この状態をコンフリクト
していると言います。
複数人で同じリモートリポジトリを更新していたら、こんなことも起こる可能性があります。
簡単に試してみましょう。まず、リモートリポジトリ側でREADMEの内容を全て削除して、「modify comment」と入力します。
次に、ローカルリポジトリでもREADMEの内容を修正します。
viコマンドで、READMEの内容を全て削除して、「test」と入力しましょう。
そして、ステージングに追加し、コミット・プッシュまで一気にやってみましょう。
$ vi README.md
$ git add README.md
$ git commit -m "mod README"
$ git push origin master
To https://github.com/maru-e/sample.git
! [rejected] master -> master (fetch first)
error: failed to push some refs to 'https://github.com/hoge/sample.git'
hint: Updates were rejected because the remote contains work that you do
hint: not have locally. This is usually caused by another repository pushing
hint: to the same ref. You may want to first integrate the remote changes
hint: (e.g., 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
プッシュしたらエラーが出ましたね。
リモートリポジトリでの変更とローカルリポジトリでの変更が衝突してしまって、どちらを優先すれば良いのか分からないからです。
このような状態になったら、リモートリポジトリでどんな変更がされたんだろう?と気になりますよね。
そんな時はgit fetch
でリモートリポジトリの変更内容をローカルリポジトリに取得することができます。
$ git fetch
remote: Enumerating objects: 5, done.
remote: Counting objects: 100% (5/5), done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (3/3), done.
From https://github.com/hoge/sample
7022b44..7beb0cd master -> origin/master
そして、ローカルリポジトリmaster
ブランチの最新のコミットHEAD
とリモートリポジトリ(origin)のmaster
ブランチとの差分を次のコマンドで確認できます。
$ git diff HEAD origin/master
diff --git a/README.md b/README.md
index 9daeafb..a099415 100644
--- a/README.md
+++ b/README.md
@@ -1 +1 @@
-test
+modify comment
README.mdファイルが修正されていて、ファイルの中身がローカルリポジトリでは「test」、リモートリポジトリでは「modify comment」となっているのがわかります。
もしローカルリポジトリの内容をリモートリポジトリに上書きして良いのであれば、git push -f origin master
で強制的にプッシュします。
リモートリポジトリの内容をローカルリポジトリに上書きしたい場合は、git pull origin master
で上書きされます。
差分を見て、どちらかの方法で内容を修正しましょう。