ローカルテスト環境:macOS 11
14 | 不要なブランチを削除するには?#
git branch -d <BRANCH_NAME>
-d
:--delete
- 条件付きでローカルブランチを削除
- ❗️条件:そのブランチが上流ブランチ(ローカルブランチに対応するリモートブランチ、設定可能)または HEAD(現在のブランチ)にマージされている場合にのみ、削除が成功する
git branch -D <BRANCH_NAME>
-D
:--delete --force
- ローカルブランチを強制的に削除
- 削除にリスクがないと確信している場合に使用できる
PS:
- 現在のブランチは削除できません。削除する必要がある場合は、まず
git checkout <BRANCH_NAME>
でブランチを切り替えてください。 - リモートブランチを削除するには:
git push <REMOTE> --delete <BRANCH_NAME>
git fetch -p / --prune
でブランチリストを同期すると、リモートで削除されたブランチは表示されなくなります。
15 | 最新のコミットメッセージを変更するには?#
git commit --amend
を入力すると、テキストエディタが開き、新しいコミットメッセージを変更できます。赤枠のように:
:wq
を入力して保存して終了すると、ターミナルに変更結果が表示されます:
再度コミット情報を確認します:
変更成功!
PS:git commit --amend
- 本質的には前回のコミットを置き換えるもので、メッセージの変更に限られません。
- 一般的には、リモートにプッシュする前のコミット操作を修正するために使用されます。
16 | 古いコミットのメッセージを変更するには?#
git rebase -i
を使用して、過去の数回のコミット情報を変更できます。 -i
はインタラクティブモードを使用します。
—— 具体的な手順 ——
まず git log
を使用して現在のバージョン履歴を確認します:
順番で 3 番目のコミットのメッセージを変更したい場合、その親コミットに基づいて操作する必要があります。
git rebase -i d8796c00719323800976e6c7fcfe6b02627ec6b2
コマンドを使用し、末尾に親コミットのハッシュ値を追加します(最初のコミットを変更する場合は git rebase -i --root
を使用できます)。編集画面が表示されます:
コミットの順序が逆転しました;Commands 部分には多くの使い方が見えます。
reword / r
コマンドを使用して、特定のコミットを保持しつつ、そのメッセージを変更します。以下のように:
:wq
で保存して終了すると、新しい編集画面が表示されます:
コミットのメッセージを変更し、再度 :wq
で保存して終了します。
変更成功、❗️ここで分離した HEAD ポインタが使用されていることがわかります。変更が完了した後、master ブランチの指向も更新され、コミットのハッシュ値が変更される可能性が高いことを示しています。
確認のため、再度 git log
でバージョン履歴を確認します:
順番で 3 番目のコミットのメッセージが変更され、最初の 3 つのコミットのハッシュ値がすべて変更されていることがわかります。3 番目のコミットのメッセージ以外は変更されていないことも確認できます。
⚠️:
- 一般的には自分のブランチに基づいて、統合ブランチ(チーム)にまだコミットしていない場合に使用します。そうでない場合は慎重に使用してください。統合ブランチに影響を与える可能性があります。
rebase
はリベースに一般的に使用され、merge
との共通点と相違点に注目することができます。参考:- Git ブランチ - リベース—— 公式
- GIT 使用 rebase と merge の正しい姿勢—— 知乎
17 | 連続した複数のコミットを 1 つに整理するには?#
同様に git rebase -i
を使用します。
—— 具体的な手順 ——
まず git log
を使用して現在のバージョン履歴を確認します:
今、赤枠内の 3 つのコミットをマージして、ブランチ内のコミット数を減らしたいと思います。
git rebase -i --root
コマンドを使用し、末尾に親コミットのハッシュ値を追加します(最初のコミットを変更するため、--root
を使用します)。編集画面が表示されます:
マージする 3 つのコミットは上記の赤枠内にあり、順序は git log
に表示される順序とは逆です。
Commands の中の squash / s
コマンドを使用して、特定のコミットを前のコミットに統合します。以下のように変更します:
:wq
で保存して終了すると、新しい編集画面が表示されます:
2 行目を追加し、3 つのコミットを統合するメッセージとして、下の各コミットのメッセージを保持し、再度 :wq
で保存して終了します。
統合成功、❗️ここで分離した HEAD ポインタが使用されていることがわかります。変更が完了した後、master ブランチの指向も更新されました。
git log
でも統合の結果を確認できます。2 つのコミットのハッシュ値が変更されていることがわかります。コミットのメッセージまたは親コミットの指向が変更されたためです。
PS:
- 統合後、一部のコミットが不要になるため、git はクリーンアップを行います。
gitk --all
を使用してこの時のブランチの状況を観察します:
- 2 つの木が現れ、2 つのブランチ間に関連がなくなったことがわかります。
- これは master ブランチのルートコミットが変更されたためです。
18 | 間隔のあるいくつかのコミットを 1 つに整理するには?#
コマンド: git rebase -i
git log
コマンドを使用してバージョン履歴を確認します:
赤枠で示された間隔のあるいくつかのコミットをマージしたい場合、同様に git rebase -i 76e5c9ca
コマンドを使用し、後ろに親コミットのハッシュ値を追加します。編集画面が表示されます:
マージするコミットの位置を調整し、s
コマンドを使用して以下のように変更します:
:wq
で保存して終了すると、マージの競合があることが通知されます。
上の青枠には、次に行うことができる操作が示されています。ここでは最初の方法を試みます:競合を解決します。
PS:git status
を使用して現在の推奨操作を確認することもできます:
次に readme ファイルを確認し、その中の競合を解決します。赤枠の位置のコードを削除するだけです:
その後、git add readme
を実行して、先ほどの変更を追加します。
次に、前の指示に従って git rebase --continue
コマンドを実行し、編集ボックスが表示され、メッセージ情報を入力し、:wq
で保存して終了します(競合を解決する必要がある場合もあり、上記の手順を繰り返すことができます)。
最後に git log
でバージョン履歴を確認します:
間隔のあるコミットとマージするコミットに関連がある場合、期待通りに動作せず、1 つのコミットに統合される可能性があるため、これらのコミットの内容を非常に明確に理解しておく必要があります。
PS:個人的にはあまり実用的ではなく、競合が発生しやすいと思います。
19 | ステージングエリアと HEAD に含まれるファイルの差異を比較するには?#
コマンド: git diff --cached
この図を忘れないでください:
- HEAD は現在のブランチを指し、ブランチはコミットを指します。
デモ:
readme.md ファイルを変更した後、git add readme.md
を入力して変更をステージングエリアに追加します;
次に git diff --cached
を入力して、ステージングエリアと HEAD の差異を比較します:
2 行のテキストが追加されたことが確認でき、期待通りであればコミットできます。
20 | 作業ディレクトリとステージングエリアに含まれるファイルの差異を比較するには?#
コマンド: git diff
コマンドの後にファイル名を追加することで、特定のファイルの作業ディレクトリとステージングエリアの差異を比較できます。例えば git diff readme.md
とし、もちろん複数のファイル名を追加することもできます。
21 | ステージングエリアを HEAD と同じ状態に戻すには?#
シナリオ:ステージングエリアの内容が不要になった場合、ステージングエリア👉HEAD。
コマンド: git reset HEAD
、 HEAD
の後に何も加えないと、すべてのファイルが HEAD と一致するように戻ります。
git status
を使用して、reset
前後の変化を観察できます。以下の図を参照してください:
reset
の後、変更操作は再び作業ディレクトリに戻され、git add
コマンドを使用して再度ステージングエリアに追加できます。
PS:
git diff --cached
を使用して、ステージングエリアと HEAD の内容の一致を確認できます。
git reset HEAD
と git restore --staged .
の効果は同じで、後者は git 2.23 以降に追加されたものです。
22 | 作業ディレクトリのファイルをステージングエリアと同じ状態に戻すには?#
シナリオ:作業ディレクトリで変更を行ったが、不要になった場合、ステージングエリアと同じ状態に戻したい。
コマンド: git checkout <FILENAME>
この図を再度思い出してください:
プロセスのデモ:
まず git add
を使用して、変更された readme.md ファイルを作業ディレクトリからステージングエリアに追加します:
操作前後の git diff --cached
の結果を観察し、ステージングエリアと HEAD の差異の変化を確認します。これにより、git add
が成功したことがわかります。
次に、再度変更された readme.md ファイルを通じて、git diff
を使用して作業ディレクトリとステージングエリアの差異を観察します:
赤枠部分が今回の変更です。
git status
を使用して作業ディレクトリとステージングエリアの状況を確認します:
図の上半分はステージングエリアのコミット待ちの内容で、下半分は作業ディレクトリのステージングエリアに追加待ちの内容です。
両方の部分に readme.md の変更があり、それぞれが先ほどの 2 回の変更に対応しています。
❗️この時、作業ディレクトリの readme.md ファイルの内容をステージングエリアの状態に戻したい場合は、git checkout readme.md
を使用します。
作業ディレクトリの readme.md ファイルがステージング待ちの状態でなくなったことがわかります。
PS:
git checkout
を慎重に使用してください。ファイルが戻らなくなる可能性があります。- Git 2.23 以降は、
git switch
とgit restore
を使用してgit checkout
の機能を置き換えます:git switch
はブランチを切り替える機能を置き換え、git restore
は作業ディレクトリのファイルを復元する機能を置き換えます。 git checkout <FILENAME>
とgit restore <FILENAME>
の効果は同じで、後者は git 2.23 以降に追加されたものです。
23 | ステージングエリアの一部ファイルの変更を取り消すには?#
コマンド: git reset HEAD [FILENAME]
、第 21 節と似ていますが、コマンドの後に具体的なファイル名を追加することもでき、複数のファイルを指定することもできます。
以下の例では、ステージングエリアの変更が 1 つずつ作業ディレクトリに戻される様子を示しています:
作業ディレクトリの変更を再度ステージングエリアに追加したい場合は、git add
コマンドを使用できます。
24 | 最近の数回のコミットを消去する#
コマンド: git reset --hard <HASH_OF_COMMIT>
、HEAD のコミット指向を変更し、ステージングエリアと作業ディレクトリの内容をそのコミットに戻します。
以下の例を見てください:
git reset --hard
前後の 2 つの点を観察します:
1)git log
を通じて HEAD の指向が 2 つのコミットに後退したことがわかります;
2)git diff
を通じて作業ディレクトリとステージングエリアの差異が存在から無に変わったことがわかります。
25 | 異なるコミットの特定のファイルの差異を確認する#
コマンド: git diff <HASH_OF_COMMIT> <HASH_OF_COMMIT> [-- FILENAME]
最後に特定のファイルを追加します。追加しない場合は、すべてのファイルの差異が表示されます;
<HASH_OF_COMMIT>
は直接ブランチ名に置き換えることができ、ブランチ名は本質的にコミットを指します。
PS:--
を加えることで Git の意図をより明確にすることができます。
26 | 正しいファイル削除の方法#
コマンド: git rm <FILENAME>
効果は以下の通りです:
本質的にはファイルを削除し、この削除操作を作業ディレクトリとステージングエリアに同期させることに相当します。これは次のように等しいです:
まず git reset --hard HEAD
を使用して作業ディレクトリとステージングエリアを HEAD の状態に戻します;
次に git status
を使用して、rm
ファイルと git rm
ファイル後の作業ディレクトリとステージングエリアの状態をそれぞれ観察します:
1)前者は作業ディレクトリを変更しましたが、ステージングされていません;
2)後者はステージングエリアを同期させました。この時、今回の変更をコミットできます。
27 | 開発中に緊急タスクが入った場合の対処法#
緊急タスクが入った場合、現在の作業がまだ未完成である場合、どうすればよいでしょうか?
git stash
:現在の作業ディレクトリとステージングエリアの内容を追加のスタックに移動します。これは追跡されているファイルにのみ有効です。
緊急タスクが完了したら、先ほどの未完成の作業を復元する必要があります。まず、stash した内容を確認します。
git stash list
:stash の記録リストを表示します。
次に、最近の stash 内容を作業ディレクトリに復元します。
git stash apply
:スタックのトップの保存記録を復元し、記録リストにはその記録が保持されます。
git stash pop
:スタックのトップの保存記録を復元し、記録リストからその記録を削除します。
- PS:特定の記録を指定して復元することもできます。
プロセスのデモ:
緊急タスクが入ったため、まず未完成の内容を stash します。
この時、stash 記録リストに記録 {0} が追加され、現在の作業ディレクトリとステージングエリアはクリーンな状態になりました。
緊急タスクが終わったら、最近の記録を stash から復元します。
apply
は stash 記録を消去せず、復元された内容は作業ディレクトリに置かれ、以前に stash したのはステージングエリアの内容です。
次に別の方法で復元します。pop
を使用し、--index
パラメータを追加します。
pop
はその stash 記録を消去し、復元された内容は stash した時と同じステージングエリアに置かれます。--index
は実際にはステージングエリアも復元されることを意味します。
PS:
WIP は Work in progress の略で、作業中のことを示し、引き伸ばされた意味として「現在作業中のコードはまだ独立して実行できず、未完成である」ということを示します。
28 | Git 管理が不要なファイルを指定するには?#
方法: .gitignore
ファイルにファイルタイプまたはファイル名を宣言するだけです(必ず .gitignore
である必要があります)。
doc / と doc の違いのデモ:
1)doc/:フォルダを無視しますが、同名のファイルは無視しません。
doc フォルダを作成し、その中に readhim ファイルを追加します。
.gitignore
ファイルに doc/
を追加すると、Git は doc フォルダの追跡を無視します。
しかし、doc フォルダを docファイルに変更すると、Git は doc ファイルの追跡を無視しません。
2)doc:フォルダと同名のファイルの両方を無視します。
無視ルール doc に対しては、ファイルとフォルダの両方が Git による追跡を無視されます。
⚠️:
- よく使われるワイルドカード
*
は同類のファイルを無視します。 - ファイルがすでに追跡されている場合、
.gitignore
ファイルは効果がありません。- もしコミット後に無視したいファイルがある場合は、無視したいファイルを
.gitignore
ファイルに追加し、git rm --cached FILENAME
の方法で追跡を無視します。
- もしコミット後に無視したいファイルがある場合は、無視したいファイルを
- GitHub で新しいリポジトリを作成する際に、適切な.gitignore ファイルを追加するオプションがあります:(とても親切❤️)
PS:異なる言語やプロジェクトに対する一般的な .gitignore
ファイルは、github/gitignoreリポジトリを参考にできます。
29 | Git リポジトリをローカルにバックアップするには?#
関連コマンド: git clone
、 git remote
、 git push
一般的な転送プロトコル:ローカルプロトコル、http/https プロトコル、ssh プロトコル。後者の 2 つが作業中に最も一般的です。
転送プロトコルは 2 つのカテゴリに分けられます:ダミープロトコルとスマートプロトコル。ここではローカルプロトコルの例を示します:
1)/Path/to/.git;2)file:///Path/to/.git
前者はダミープロトコル、後者はスマートプロトコルです。
では、Git バックアップ時の両者の違いは何でしょうか?
スマートプロトコルはダミープロトコルに比べて、1)転送進捗が見える、2)転送速度が速いです。
スマートプロトコルとダミープロトコルの効果の比較:
pwd
を使用して、以前のデモで使用したリポジトリのアドレスを取得しました: /Users/double/Desktop/test
現在、2 つのプロトコルを使用して、リポジトリを別の場所、test_remote ディレクトリにバックアップします。
ダミープロトコル
⚠️: --bare
は裸リポジトリを作成することを示し、作業ディレクトリを持たないリポジトリで、サーバーとして便利です。バックアップは.git フォルダなので、アドレスには /.git
を追加する必要があります。最後の ya.git
はリポジトリ名を示します。
スマートプロトコル
test.remote ディレクトリに戻り、スマートプロトコルを使用して、file://
プレフィックスを追加します。
比較すると、視覚的な違いが見えます:ダミープロトコルは進捗バーがなく、スマートプロトコルには進捗バーがあります。
上記はリモートからローカルにリポジトリをクローンするプロセスを示しましたが、ローカルリポジトリをリモートにプッシュするにはどうすればよいでしょうか?
元のリポジトリに戻り(ここで元のリポジトリの役割はリモートからローカルに変わります)、new
という名前のブランチを新しく作成します。
この時、リモートの intel.git リポジトリにはまだ 3 つのブランチしかありません:
ローカルにリモートサーバーを追加します:
git remote add intel file:///Users/double/Desktop/test_remote/intel.git
PS: intel
はサーバーのエイリアスで、後ろはサーバーのアドレスで、スマートプロトコルを使用します。
git remote -v
を使用して、詳細なサーバー情報を確認できます。
次にプッシュを行います: git push REMOTE_NAME
コマンド
⚠️:直接プッシュするとエラーが発生します。まず上流を設定する必要があります。
再度リモートの intel.git リポジトリのブランチ状況を確認します:
ブランチ new
がプッシュされたことが確認できます~
ここまで学んだことの中で、以前知らなかったことはありますか?ぜひ交流しましょう~