← プログラミングページの先頭へ

Git: バージョン管理とチームコラボレーション

Git は、コード履歴、ブランチ、マージ、チーム コラボレーションを管理するための分散バージョン管理システムです。

1.コアモデル

Working Tree(ワークスペース)
       ↓ git add
Index / Staging Area(ステージングエリア)
       ↓ git commit
Local Repository(地元の倉庫)
       ↓ git push
Remote Repository(遠隔倉庫)

3 つの主要な領域:

エリア機能
Working Tree現在編集中のファイル
Staging Area提出書類の内容
Local Repository保存された Commit 履歴

注: git add はファイルの追跡を開始するだけでなく、さらに重要なことに、の現在のファイル内容のスナップショット を一時記憶域に配置します。

したがって、同じファイルにステージングされた変更とステージングされていない変更の両方が含まれる可能性があります。

2. 中心となる概念

Repository

Git ウェアハウスには、送信オブジェクト、ブランチ参照、履歴レコードなどの情報が含まれています。

git init
git clone <url>

通常、ウェアハウスには .git/ ディレクトリが含まれます。

Tracked / Untracked

  • Tracked: ファイルはすでに Git によって追跡されています。
  • Untracked: Git ファイルはまだ追跡されていません。
  • Modified: ファイルの内容が変更されました。
  • Staged: 変更は一時記憶域に入りました。
git status

.gitignore

まだ追跡されていないファイルを無視するために使用されます。

node_modules/
.env
dist/
__pycache__/

すでに追跡されているファイルは、.gitignore が追加されても引き続き追跡されます。

トレースを停止しますが、ローカル ファイルは保持します。

git rm --cached .env

機密情報が Git 履歴に送信された場合、追跡を停止しても既存の履歴内の漏洩コンテンツは消去されません。対応するキーを取り消し、履歴を消去することも検討する必要があります。

Commit

Commit は、特定の時点でのプロジェクトの完全なスナップショットとして理解でき、親 Commit、作成者、時刻、投稿情報などのメタデータを保存します。

A ── B ── C ── D
               ↑
              main

各 Commit には固有のオブジェクト ID があります。

HEAD は通常、現在のブランチへのシンボリック参照です。

HEAD → main → D

一般的な表現:

表現意味
HEAD現在のコミット
HEAD^最初の親コミット
HEAD~2最初の親コミットに沿って 2 回前進します
HEAD~3最初の親コミットに沿って 3 回前進します
HEAD^22 番目の親コミット、Merge Commit で共通

HEAD^3 は最初の 3 つのコミットではなく、3 番目の親コミットです。

Detached HEAD

Commit に直接切り替えます。

git switch --detach abc123

現時点では、HEAD はブランチではなく Commit を直接指します。

過去のコードを確認するのに適しています。ここで開発を続ける準備ができている場合は、新しいブランチを作成する必要があります。

git switch -c fix/old-version

3. ローカル支店とリモート追跡支店

Git は分散バージョン管理システムです。

GitHub:
main         → C

Local:
main         → B
origin/main  → C
  • main: ローカル支店。
  • origin/main: ローカルに保存されたリモート追跡ブランチのステータス。
  • origin: リモート倉庫の名前。通常は clone によって自動的に作成されます。

新しいコミットがリモートで生成された場合:

GitHub:
A ── B ── C ── D

Local:
main         → B
origin/main  → C

実行:

git fetch origin

更新日:

main         → B
origin/main  → D

ただし、ローカルの main は直接変更されません。

fetch および pull

git fetch origin

現在の作業ブランチを直接マージせずに、リモート更新を取得します。

git pull

最初に Fetch、次に Merge、Rebase、または構成に応じて Fast-forward のみ。

以下を明示的に指定します。

git pull --no-rebase
git pull --rebase
git pull --ff-only

偶発的なマージ コミットを回避したいシナリオでは、--ff-only を使用します。

4. 基本コマンド

初期化と構成

git init

git config --global user.name "Your Name"
git config --global user.email "you@example.com"

git clone <url>

ステータスの表示

git status

git branch
git branch -a
git remote -v

ステージングと提出

git add src/foo.ts

git add .

git commit -m "feat: add user profile"

git add . 現在のディレクトリおよびサブディレクトリ内の修飾された追加、変更、および削除を一時記憶領域に追加します。

送信する前に次のことを確認することをお勧めします。

git diff --staged

違いを表示する

# ワークスペースとステージングエリア
git diff

# 一時保管場所や HEAD
git diff --staged

# 2つ Commit
git diff A B

# 単一のコミットを表示する
git show <commit>

履歴を見る

git log

git log --oneline

git log --oneline --graph --decorate --all

git log -n 5

git log --author="Author Name"

その中には:

git log --oneline --graph --decorate --all

ブランチおよびマージ関係の表示に適しています。

5.支店管理

作成して切り替える

git branch feature/login

git switch feature/login

# 作成して切り替える
git switch -c feature/login

削除

# 安全な削除
git branch -d feature/login

# 強制削除
git branch -D feature/login

# リモートブランチを削除する
git push origin --delete feature/login

-d は、ブランチが適切にマージされたことをチェックします。 -D は、この安全性チェックをスキップします。

名前の変更

git branch -m new-name

Upstreamでプッシュ

git push -u origin feature/login

-u は、ローカル ブランチと上流ブランチの間の追跡関係を確立します。

その後、通常は次のことが可能になります。

git push
git pull

ただし、実際の Push ターゲットも Git 構成の影響を受けます。

6. Merge: ブランチをマージします

仮定:

        C ── D  feature
       /
A ── B ── E     main

main:

git switch main
git merge feature

結果:

        C ── D ──┐
       /          │
A ── B ── E ───── M
                 ↑
                main

Merge Commit M には 2 つの親コミットがあります。

Git は、共通の先祖と両側の変更に基づいて 3 方向のマージを実行します。

Fast-forward Merge

main が新しいコミットを生成しない場合:

A ── B         main
      \
       C ── D  feature

実行:

git switch main
git merge feature

結果:

A ── B ── C ── D
                 ↑
             main, feature

このとき、Git は分岐ポインタを前方に移動するだけでよく、必ずしも新しい Merge Commit を作成する必要はありません。

7. Rebase: リベース

仮定:

A ── B ── C        main
      \
       D ── E      feature

feature ブランチで実行します。

git switch feature
git rebase main

結果:

A ── B ── C        main
             \
              D' ── E'  feature

Rebase ブランチ内のコミットを新しいベース コミットに再適用した後。

通常、親コミットなどの情報の変更により、新しい Commit ID が生成されます。

Merge および Rebase

コントラストMergeRebase
本来の歴史予約する再生されたコミットを書き直す
図を送信するフォークと Merge Commit が生成される可能性があります通常はより直線的です
共有ブランチ比較的安全な勝手に書き換えてはいけません
一般的な用途機能ブランチをマージする個人開発ブランチを更新

共通原則:

  • Rebase の書き換えを避けるために、チームで共有されている履歴を優先する必要があります。
  • 独立して保守される機能ブランチの場合、Rebase を使用して履歴を整理できます。
  • 詳細は、チームの Git ワークフロー仕様の対象となります。

8. Merge / Rebase の競合

競合の例:

<<<<<<< HEAD
const timeout = 30;
=======
const timeout = 60;
>>>>>>> feature

最終的なコンテンツは手動で決定し、競合するマーカーを削除する必要があります。

Merge 競合

git status

# 競合ファイルを変更する
git add config.ts

git merge --continue

適切な状況で git commit を実行してマージを完了することもできます。

Merge をあきらめます:

git merge --abort

Rebase 競合

git status

# 競合ファイルを変更する
git add config.ts

git rebase --continue

Rebase をあきらめます:

git rebase --abort

注: Rebase の場合、ours および theirs の意味は通常の Merge と混同されやすく、「自分のコード」と「他人のコード」として機械的に理解できません。

9. Restore、Reset、Revert

3 つの命令はすべて取り消しに関連していますが、責任は異なります。

git restore

主にワークスペースまたは一時記憶領域にファイルの内容を復元します。

# ファイルに対するステージングされていない変更を破棄し、元の状態に戻します。 Index
git restore src/foo.ts

# 一時保存をキャンセルし、ワークスペースの変更を保持します
git restore --staged src/foo.ts

# ステージング領域とワークスペースの両方が復元されます。 HEAD
git restore --source=HEAD --staged --worktree src/foo.ts

注: デフォルトでは、git restore file はソースとして Index を使用しますが、これは必ずしも HEAD と等しいわけではありません。

git reset

現在のブランチの Commit ポインタを移動し、モードに応じてステージング領域とワークエリアを変更するかどうかを決定できます。

モードHEADを移動するIndexをリセットWorking Treeをリセット
--softはいいいえいいえ
--mixed (デフォルト)はいはいいいえ
--hardはいはいはい

たとえば:

# 最後を元に戻す Commit,ステージングを続ける
git reset --soft HEAD~1

# 最後を元に戻す Commit,ワークスペースの変更を保持しますが、ステージングは解除します
git reset HEAD~1

# 指定されたコミットに戻り、ワークスペースとステージング領域をリセットします。
git reset --hard abc123

--hard は破壊的であり、コミットされていない作業が失われる可能性があります。他の人によってプルされたコミットの場合は、通常、Reset の後に強制的にプッシュしないでください。

ファイルを指定する場合:

git reset HEAD -- src/foo.ts

現在のブランチを移動せずに、ファイルの一時コンテンツを HEAD に復元するだけです。

git revert

元の履歴を削除せずに、新しいリバース コミットを作成します。

A ── B ── C ── D
               ↓ revert C
A ── B ── C ── D ── E
git revert <commit>

チームの共有ブランチに対する Push のコミットに適しています。

選び方は?

需要おすすめ
ステージングされていない変更を破棄するgit restore
アンステージgit restore --staged
プッシュされていない Commit を元に戻し、変更を保持しますgit reset --soft
共有ブランチの Commit を元に戻すgit revert
ローカルの変更を完全に破棄してロールバックしますgit reset --hard、慎重です

10. 最終変更 Commit

提出情報を変更します。

git commit --amend

ファイルを追加するのを忘れました:

git add forgotten.py
git commit --amend --no-edit

--amend は実際には、現在のブランチの末尾にある古い Commit を置き換える新しい Commit を作成します。

古いコミットが共有ブランチに Push されている場合は注意してください。

11. Stash: 変更を一時的に保存します

git stash は、コミットされていない作業を一時的に保存するために使用されます。

git stash

デフォルトでは、追跡されたファイルのステージングされた変更とステージングされていない変更は保存されますが、通常の Untracked ファイルは保存されません。

新しいファイルを含める必要があります。

git stash push -u -m "WIP: profile form"

よく使用されるコマンド:

git stash list

# 最新のものを復元する Stash,そしてリストから削除します
git stash pop

# 復元するが保持する Stash
git stash apply

# 指定されたものを削除する Stash
git stash drop stash@{0}

開発中の一時的な切り替え作業に適しています。

注: stash pop は競合する可能性があり、回復プロセスが成功しない可能性があります。

12. Cherry-pick: 指定された提出物を選択します

仮定:

main:     A ── B ── C

feature:  A ── B ── D ── E

D の変更を main に適用したいだけです。

git switch main
git cherry-pick <D>

結果:

main: A ── B ── C ── D'

該当するシナリオ:

  • 他のブランチから Bug Fix を選択します。
  • ブランチをリリースするために特定の修正をバックポートします。
  • 機能ブランチ全体をマージしたくない。

通常、Cherry-pick は新しい Commit を作成します。

13. Reflog: 失われたコミットの取得

git reflog は、ローカル HEAD および参照の履歴変更の一部を記録します。

git reflog

たとえば、次のように実行します。

git reset --hard HEAD~2

ロールバックが間違っていることがわかった場合は、まず次のコマンドを実行します。

git reflog

オリジナルの Commit ID を見つけます。

次に、回復ブランチを作成します。

git branch recovery <commit-id>

または、安全を確認してから再度 Reset をお試しください。

次の点に注意する必要があります。

  • Reflogは主にローカル記録です。
  • Reflog エントリは期限切れになります。
  • コミットされていない変更をすべて取得できるという保証はありません。

誤って Commit を見つけた後に見つからない Reset、Rebase を回復するのに特に適しています。

14. Tag: バージョンラベル

Tag は通常、リリース バージョンをマークするために使用されます。

軽量タグ:

git tag v1.0.0

注タグ:

git tag -a v1.0.0 -m "Release v1.0.0"

プッシュ:

git push origin v1.0.0

チェックアウト:

git tag
git show v1.0.0

Tag は Branch とは異なります。

  • Branch は通常、新しい Commit と一緒に動きます。
  • Tag は通常、特定のオブジェクトを指します。

15. 強制プッシュ

git push --force

リモートブランチ履歴は強制的に上書きされる可能性があり、これには高いリスクが伴います。

実際に独自のブランチ履歴を書き換える必要がある場合には、これを使用することをお勧めします。

git push --force-with-lease

リモート参照がローカルの期待と一致しているかどうかをチェックし、他の人の新しいコミットを上書きするリスクを軽減します。

ただし、絶対的な安全を意味するわけではありません。特にバックグラウンドでの Fetch や複雑なチーム コラボレーション シナリオでは、依然として注意が必要です。

共有 main ブランチを任意に強制的にプッシュしないでください。

16. 日々の開発ワークフロー

ステップ 1: 機能ブランチを作成する

git switch main
git pull --ff-only

git switch -c feature/avatar-upload

ステップ 2: 開発して送信する

git status
git diff

git add .
git diff --staged

git commit -m "feat: add avatar upload"

ステップ 3: プッシュする

git push -u origin feature/avatar-upload

GitHub で Pull Request を作成し、Review を待ちます。

ステップ 4: Review に従って変更します。

git add .
git commit -m "fix: validate avatar file type"
git push

ステップ 5: PR マージ後のクリーンアップ

git switch main
git pull --ff-only

git branch -d feature/avatar-upload

リモート関数ブランチがプラットフォームによって自動的に削除されない場合は、オンデマンドで削除できます。

git push origin --delete feature/avatar-upload