こちらは個人の勉強メモです
ステージング
タイトルからはズレるが、コミットする時にはステージングされたものを全てコミットするしかないので
ステージングの時点で意味のあるコミットを心がけて整理しておくことが必要となる
git status, 今コミットしたらどうなるか
インデックスのステータスの確認
git status
ワーキングディレクトリ (commit に反映されていない作業差分) の状態を表示する
一番大事。とにかく commitする前に現在のワーキングディレクトリの状態を常にこれで確認するべき。
全て commit してあったら何もないのでクリーンですと出る
git add -p, 変更を分割しながらステージング
参考
[git add -p 使ってますか?]
(https://qiita.com/cotton_desu/items/bf08ac57d59b37dd5188)
インデックスにステージングするワーキングディレクトリの新しい作業を分割することができる。
これを使うと、内容を確認しながら ステージング してくれる
git add -p
で stage this? と7 lines くらいずつ聞いてくれる。
返答で約半分にできる。かなり便利。
なお、すでにこれをするをの忘れて、
ワーキングディレクトリの新規作業を全てステージングしてしまった場合は
git reset HEAD, ステージングの取り消し
git reset HEAD
でステージングしたのを取り消せる。
git reset HEAD
Unstaged changes after reset:
M lib/posts.js
M pages/index.js
M posts/pre-rendering.md
コミットは後から取り消すことを考えると 1 ファイルずつ、 1 関数ずつしたほうがいいので、
作業した後にコミットし忘れたのを気づいたら、上記の git add -p
で少しづつステージングして
それからコミットすればコミットを細かく意味がコミットメッセージの明確なものができる
git reset --soft HEAD^
git status
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
new file: components/date.js
間違えて
git add .
でワーキングディレクトリの内容を追加してコミットもしてしまったら
git reset --soft HEAD^
した方が確実にコミットを取り消せる。ワーキングディレクトリは巻き戻さずに。
git log
コミットログの表示
git log -p
詳細コミで表示
- commit の16進数の id
- した人
- 日付時間
- コミットメッセージ
- ファイル名
- 差分のテキスト
古い順で表示されていく
commit aaaaaaaaaaa161616161616hexhexhex
Author: yourusername <yourmail@exmaple.com>
Date: Wed Jul 8 20:21:18 2020 +0900
add worked hours
diff --git a/2020/07/08.md b/2020/07/08.md
index ccf9e0d..44cce18 100644
--- a/2020/07/08.md
+++ b/2020/07/08.md
@@ -37,11 +37,15 @@
+ 15:00 ~ 17:00
+ 19:00 ~ 20:10
+3+0.5+2+1
+
+6.5時間
+
## 次回稼働予定
明日2020/07/09 木
09:30 ~ 18:30
-8h
+8時間
commit aaaaaaaaaaa161616161616hexhexhexhex
Author: yourusername <your@mail.com>
Date: Wed Jul 8 20:11:49 2020 +0900
Filled whole 2020/08.md report
このように詳細コミでブランチのコミットログが出てくる。
git log --oneline
1行で表示
0cf4e81 (HEAD -> 20200708-daily-report, origin/20200708-daily-report) add worked hours
b5375be Filled whole 2020/08.md report
9ecbd48 applied report template
39ce8fc made 07/08.md
133627b (origin/master, origin/HEAD, master) Merge pull request #2 from kodansha/20200702-daily-report
9d49266 replace hatena to Hatena
d06148b 、。に統一
488fc83 add lines to before and after headers and fence blocks
cb6dbba changed docker to Docker
683f641 integrated things name to `GitHub`, `Qiita`, `Qiita Teams`, `Docker`,
0e2f469 mod view
54d0ad1 Update issue templates
44e086c Update issue templates
043aab3 (origin/hoge, hoge, 20200701-report) wrote 0702
a4a14f4 (origin/20200702-daily-reoprt) add 2020/ 07/ dir, and ad http://01.md
e31b897 first commit
91eb15c Initial commit
1行ずつ コミット id の16進数, コミットメッセージが見れる。
この中からgit rebase -i
の引数を選べる
git log --graph --oneline --decorate --all
グラフ で1行でデコって表示
git log --graph --oneine --decorate --all
ブランチが全て枝分かれして色がついて出る。
push される コミットの確認
[git でpush前にcommitを確認する方法]
(https://hacknote.jp/archives/12028/)
git log origin/master..master
これで今何が push されるのか確認できる
git log origin/master..master
commit yourhexyourhexyourhex (HEAD -> master)
Author: yourusername <yourmail@exmaple.com>
Date: Thu Sep 17 17:51:59 2020 +0900
add 404 js
このように現在のローカルリポジトリの最新と、リモートリポジトリの最新の差分が取れる。
reflog, 過去のすべての行動の履歴
コミット の管理コマンドという趣旨からは外れるが、関連コマンドとしてあげておく
参考
http://www-creators.com/archives/1116#6
デフォルトではHEADの移動をすべて表示します。
HEAD@{xx}というのは、過去何番目のHEADの状態かということですね。
元に戻したいポイントがわかれば、あとは、git reset --hard で強制的に巻き戻します。
指定のコミットに、ブランチ状態を強制上書き。全部取り消し。
git reset --hard HEAD@{14}
のように。
危険なので推奨されていないチームもある。
現在所属しているチームでは reset hard も rebase も, feature ブランチで行うならば非推奨ではない。
コミット を綺麗に保つ方が優先されている。
実際に実行すると
git reflog
153a2e9 (HEAD -> 20200820-daily-report, origin/20200820-daily-report) HEAD@{0}: commit: 2020年08月20日の日報
2f3704d (origin/master, origin/HEAD, master) HEAD@{1}: checkout: moving from master to 20200820-daily-report
2f3704d (origin/master, origin/HEAD, master) HEAD@{2}: pull origin master: Fast-forward
15e4f2b HEAD@{3}: checkout: moving from 20200818-daily-report to master
e3c21fb (origin/20200818-daily-report, 20200818-daily-report) HEAD@{4}: commit: rm inside secret data
688d299 HEAD@{5}: checkout: moving from 20200819-daily-report to 20200818-daily-report
703b65c (origin/20200819-daily-report, 20200819-daily-report) HEAD@{6}: commit: 2020年08月19日の日報
15e4f2b HEAD@{7}: checkout: moving from master to 20200819-daily-report
15e4f2b HEAD@{8}: checkout: moving from 20200818-daily-report to master
688d299 HEAD@{9}: commit: 2020年08月18日の日報
15e4f2b HEAD@{10}: checkout: moving from master to 20200818-daily-report
15e4f2b HEAD@{11}: checkout: moving from 202008180daily-report to master
このように
- id
- 動作の HEAD(現在地)からの位置
- 動作の内容。commit や checkout など
が 1行ずつ出る
コミット だけの履歴が出る git log と違って checkout などの「行動」も出る。
merge と rebase
mergeとrebaseは共に履歴を統合するコマンドだが、特徴が異なる
merge
変更内容の履歴はそのまま残るが、履歴が複雑になる。
rebase
履歴は単純になるが、元のコミットから変更内容が変更される。そのため、元のコミットを動かない状態にしてしまうことがある。
上司によると
merge と rebase は、チームの運用方針に応じて使い分けます。
例えば、履歴を一本化するように運用をするのであれば
トピックブランチに統合ブランチの最新のコードを取り込む場合は rebase を使う
統合ブランチにトピックブランチを取り込む場合は、まず rebase してから merge
というように使い分けます。
とのことで
トピック(リモートの最新の)ブランチをとってくる場合、コンフリクトが起きたら
rebase でこちら側の歴史を改変して
統合ブランチに push する。
git reset
コミットを「ひとます戻る」コマンド
reset は、ブランチの最新コミットから順番に記録を消していくもの
ソフトとハードの二種類がある。
ソフトは単にステージングしたものの取り消しで、実際のファイルの変更は戻らないが
--hard をつけるとワーキングツリーがリセットされるので、実際のファイルのコミットする前の変更が消える。
git status
On branch master
No commits yet
Changes to be committed:
(use "git rm --cached <file>..." to unstage)
new file: .browserslistrc
new file: .gitignore
new file: .ruby-version
new file: Gemfile
new file: Gemfile.lock
この例だと
git status で見るとコミットはされていないが、ステージングに
Gemfile など大量のファイルが上がっている。
これを
git reset
git status
On branch master
No commits yet
Untracked files:
(use "git add <file>..." to include in what will be committed)
.browserslistrc
.gitignore
.ruby-version
Gemfile
Gemfile.lock
nothing added to commit but untracked files present (use "git add" to track)
git reset して git status で確認してみると
git 管理下にステージングされていたファイルが Untracked files
としてステージングをリセットされている。
ちなみに @^
が HEAD のエイリアス。短く打てる。
git reset --soft HEAD^
git reset --soft HEAD^
これををすればつまりコミットが一つ無かったことになる。
つまりやるたびに1つ git log の表示が消えていく
なお、branch を切る前の master から生成する前までも戻れてしまう。注意。
git reset --hard (HEAD^)
コミット単位でワーキングディレクトリの作業ごと消し去る。
デフォルトだと最後のコミットまで巻き戻す。
「いろいろ作業して動かなくなってわけわからなくなったからとりあえず前回のコミットしてある動く状態まで戻すぞ!」
といった使い方をしているが、結構危険なコマンドなので、
対策としてわかりやすい削除すると書いた名前のリモートブランチにバックアップをあげておいてからこれをした方がいい。
参考
[[Git]コミットの取り消し、打ち消し、上書き]
(https://qiita.com/shuntaro_tamura/items/06281261d893acf049ed)
--hardオプション:コミット取り消した上でワークディレクトリの内容も書き換えたい場合に使用。
--softオプション:ワークディレクトリの内容はそのままでコミットだけを取り消したい場合に使用。
git stash -u / git stash apply で変更を一時的に逃して移動する
ブランチをまちがえて作業してしまった場合に便利。
とりあえず
git stash -u
で最後のコミットまでの変更内容を stash という一時的な場所において
git checkout で適切なブランチに戻って
git stash apply
で変更内容を退避させる前の状態に戻してステージングを始めるといった使い方をよくしている。
git rebase -i, ピンポイント history 修正
コミットログが汚くなってしまった時には必要な歴史修正コマンド
interactive の i、 双方向。会話型。
参考
[コミット履歴の改善に役立つ git rebase -i 5つの使い方]
(https://qiita.com/kmt/items/42f7f5678d0fc1126d79)
git rebase -i <hash>
これで git log で出てきたコミットの id を指定すると
git rebase -i 043a...
pick 89bc90e Update issue templates
pick 3b933ef 2020/07/03 日報を追加します
pick d335193 rebased del 07/02, 07/03
pick 7b956fd add 2020/07/03 daily report
pick 523ce31 Revert "wrote 0702"
pick 2b6286f Revert "Update issue templates"
Rebase 043aab3..2b6286f onto 7b956fd (6 commands)
指定したhashの一つ前までのコミットが vim で開かれる。
ここで pick を 変更する。詳細は
# Commands:
# p, pick <commit> = use commit
# r, reword <commit> = use commit, but edit the commit message
# e, edit <commit> = use commit, but stop for amending
# s, squash <commit> = use commit, but meld into previous commit
# f, fixup <commit> = like "squash", but discard this commit's log message
となっている。
非常に難しく、しくじると非常にスパゲティーなコミットログになってしまう、
git で一番難しいコマンドである (私の知る限りでは)
なお、この操作の後は push -f origin <branchName>
が必要
参考
[ git commit を取り消して元に戻す方法、徹底まとめ ]
(http://www-creators.com/archives/1116)
過去のコミットをhistoryから削除する
git rebase は、ブランチの歴史を修正するためのコマンドで、ブランチ履歴の整理のために、よく使うのgit コマンドの1つです。「i」は「interactive(インタラクティブ)」の略です。
例えば、下記のように取り消したいコミットの直前を指定します。あくまで「リベース」を実行していますので、「どのコミットを取り消したいか?」ではなく、「どのコミットに対して、リベースをかけるか」を引数で指定する点を意識して下さい。
現在のブランチを、 までリベース。
git rebase -i <commit>
一般的に、git rebase -i は、「s(コミットを直前のコミットに統合)」「f(sと一緒。ログも破棄)」などを利用して、ログをキレイに整える目的で利用することが多いでしょう。
git rebase --abort
で今のrebaseをなかったことにできる
git rebase -i e31b897
CONFLICT (add/add): Merge conflict in 2020/07/03.md
Auto-merging 2020/07/03.md
error: could not apply a18f98b... add 2020/07/03 daily report
Resolve all conflicts manually, mark them as resolved with
"git add/rm <conflicted_files>", then run "git rebase --continue".
You can instead skip this commit: run "git rebase --skip".
To abort and get back to the state before "git rebase", run "git rebase --abort".
Could not apply a18f98b... add 2020/07/03 daily report
参考
[git rebase --skip を知らなくて沼から出れなくなった]
(https://qiita.com/oke-py/items/3ed27931986d4fe09818)
git rebase -i
の最中では
git rebase --skip
をしないと抜け出せない場合があるので注意。
git revert
コミットの作業の取り消しコミットを作成する
git revert コミットのハッシュ値
作業ツリーを指定したコミット時点の状態にまで戻し、コミットを行う(コミットをなかったことにはせず、逆向きのコミットをすることで履歴を残す)
例えば hoge.md
を削除したコミットを revert に指定すると、
逆方向のコミットとして、hoge.md
を作成したコミットが作成された。
本番環境で巻き戻しをする時にはこのコマンドを使うらしい。
それをスムースに行うために 提出する feature ブランチではわかりやすいコミット履歴にしておくことが重要。