Git + Linux の基本操作 - バージョン管理を始めよう

Git + Linux の基本操作 - バージョン管理を始めよう

この記事で解決できること

  • Git の 最小限のセットアップ ができる
  • git init / add / commit / push基本フロー が身につく
  • Linux 特有の落とし穴(権限・改行コード・実行ビット)を回避できる
  • SSH 鍵認証で GitHub / GitLab に push できるところまで到達する

結論(最短ルート)

  1. インストール:sudo apt install git
  2. 初期設定:git config --global user.name / user.email
  3. リポジトリ:git init または git clone <url>
  4. 反復:git statusgit addgit commit -m "..."
  5. 共有:git remote addgit push -u origin main

前提(対象環境)

  • Ubuntu / Debian 系 Linux(22.04 以降を想定)
  • bash または zsh
  • GitHub / GitLab / 自前 Git サーバを SSH 経由で利用

1. インストールと初期設定

1-1. インストール

$ sudo apt update
$ sudo apt install -y git
$ git --version
git version 2.43.0

RHEL / Fedora 系は sudo dnf install git、macOS は brew install git

1-2. グローバル設定(最初に 1 度だけ)

$ git config --global user.name "Your Name"
$ git config --global user.email "you@example.com"
$ git config --global init.defaultBranch main

init.defaultBranch main を設定すると、以後 git init で自動的に main ブランチが作られる(GitHub が 2020 年以降の標準として採用)。

1-3. 設定の確認

$ git config --list --global

--global~/.gitconfig に書き込まれる。リポジトリごとに上書きしたい場合は、当該リポジトリ内で --global を外して実行する(.git/config に保存)。

2. リポジトリを用意する:init / clone

2-1. 既存ディレクトリで始める

$ cd ~/projects/myapp
$ git init
$ ls -la .git

.git/ ディレクトリが作成された時点で「Git 管理下」になる。中身を直接編集する必要は通常ない。

2-2. リモートを clone する

# HTTPS(簡単だが PAT 必要)
$ git clone https://github.com/user/repo.git

# SSH(鍵を登録しておけば後はノータッチ・推奨)
$ git clone git@github.com:user/repo.git
$ cd repo

GitHub の HTTPS 認証は 2021 年以降パスワード認証が廃止され、Personal Access Token (PAT) が必須。日常使いでは SSH 経由の方が摩擦が少ない(§6 で鍵セットアップを解説)。

3. 基本フロー:status → add → commit

Git の日常作業は 「変更を見る → 含める → スナップショットする」 の繰り返し。

3-1. 状態を確認する

$ git status
On branch main
Untracked files:
  (use "git add <file>..." to include in what will be committed)
        README.md

3-2. 変更をステージへ

$ git add README.md           # 単一ファイル
$ git add src/                # ディレクトリ単位
$ git add -p                  # 変更ハンク単位で対話的に選ぶ

git add . は便利だが、.env などの 秘密ファイルを誤って含めやすい。必ず git status を確認してから add する習慣を。

3-3. コミット(スナップショット保存)

$ git commit -m "Add README"
[main (root-commit) abc1234] Add README
 1 file changed, 5 insertions(+)
 create mode 100644 README.md

3 コマンドのメンタルモデル

  • status = 「今どうなってる?」
  • add = 「次のコミットに含める」
  • commit = 「スナップショット確定」

4. 履歴を見る:log / diff

4-1. コミット履歴

$ git log --oneline --graph --decorate -10
* abc1234 (HEAD -> main) Add README
* def5678 Initial commit

実用には次のエイリアスがおすすめ。

$ git config --global alias.lg "log --oneline --graph --decorate --all -20"
$ git lg

4-2. 差分を見る

$ git diff                    # ワーキングツリー vs ステージ
$ git diff --staged           # ステージ vs HEAD
$ git diff HEAD~1 HEAD        # 直前コミットと現在
$ git diff main..feature      # ブランチ間

4-3. ファイル単位の履歴

$ git log --follow -p src/index.js

--follow でリネームを跨いで追跡できる。

5. リモートと連携する:push / pull

5-1. リモートを追加

$ git remote add origin git@github.com:user/repo.git
$ git remote -v
origin  git@github.com:user/repo.git (fetch)
origin  git@github.com:user/repo.git (push)

5-2. push(初回)

$ git push -u origin main

-u--set-upstream)を付けると、以後の git push / git pull で remote / branch 指定を省略できる。

5-3. pull / fetch

$ git pull              # fetch + merge を自動実行
$ git fetch             # 取得だけ
$ git log HEAD..origin/main   # 自分より進んでいる差分を確認

チーム作業での pull 事故

  • git pull は merge を 自動実行 するため、ローカル変更との衝突が起きやすい。
  • 不安なときは git fetchgit log HEAD..origin/maingit merge の 3 段階に分けると安全。
  • リベース運用なら git config --global pull.rebase true を検討。

6. SSH 鍵認証のセットアップ

6-1. 鍵ペアの生成

$ ssh-keygen -t ed25519 -C "you@example.com"
$ cat ~/.ssh/id_ed25519.pub

ed25519 は軽量・高速で、現在の標準アルゴリズム。古い環境向けに RSA を使う場合は -t rsa -b 4096

パスフレーズは 必ず設定する(漏洩時の被害を限定するため)。ssh-agent にロードしておけば毎回入力する手間は省ける。

6-2. GitHub / GitLab に公開鍵を登録

~/.ssh/id_ed25519.pub末尾 .pub の方)の内容をコピーし、GitHub の Settings → SSH and GPG keys から追加する。秘密鍵 id_ed25519 は絶対に公開しない。

6-3. 接続テスト

$ ssh -T git@github.com
Hi user! You've successfully authenticated, but GitHub does not provide shell access.

このメッセージが出れば成功(exit code は 1 だが正常)。

7. .gitignore:Linux 特有の除外設定

# OS / エディタ
.DS_Store
*~
.*.swp
.idea/
.vscode/

# 言語ランタイム
node_modules/
__pycache__/
*.pyc
target/
build/
dist/

# 機密情報(最重要)
.env
.env.*
*.key
*.pem

# ログ
*.log
logs/

迷ったら GitHub 公式の github/gitignore リポジトリに言語別テンプレートが揃っている。

8. Linux 特有のトラブル

8-1. Permission denied(push 時)

ERROR: Permission to user/repo.git denied to other-user.
fatal: Could not read from remote repository.

原因候補:

  • SSH 鍵が GitHub に登録されていない
  • 複数アカウントの鍵が混在し、別アカウントの鍵が先にロードされている
  • リポジトリへの書き込み権限が無い(コラボレーターでない)

切り分け:

$ ssh -T git@github.com         # どのユーザーで認証されているか確認
$ ssh-add -l                    # ssh-agent にロード済みの鍵を表示

複数鍵を使い分ける場合は ~/.ssh/config でホスト別に指定する。

8-2. 改行コードの混入(CRLF / LF)

Windows 由来のファイルが混ざると、プロジェクト全体の diff が壊れる(全行変更扱いになる)。

# Linux / macOS:改行を変換せず保存(推奨)
$ git config --global core.autocrlf input

リポジトリ単位で固定する場合は .gitattributes を作成:

* text=auto eol=lf
*.sh text eol=lf
*.bat text eol=crlf

8-3. 実行ビット(chmod +x)が記録されない

$ chmod +x scripts/deploy.sh
$ git status      # 変更が出ない場合がある

明示的に mode 変更を記録する:

$ git update-index --chmod=+x scripts/deploy.sh
$ git diff
old mode 100644
new mode 100755

core.fileMode = false がリポジトリに設定されていると mode 変更が無視される。git config core.fileMode で確認可。

8-4. 大文字小文字違いのファイル名

Linux のファイルシステム(ext4 等)は case-sensitive だが、macOS / Windows は case-insensitive がデフォルト。Readme.mdREADME.md を取り違えると、Linux ベースの CI で破綻する。

# リポジトリ全体で case 違いを検出
$ git config --global core.ignorecase false

命名規約を CONTRIBUTING.md に明記し、レビューで止めるのが現実的。

9. 安全テンプレート集

初回セットアップ

git init
echo "node_modules/" > .gitignore
git add README.md .gitignore
git commit -m "Initial commit"
git remote add origin git@github.com:user/repo.git
git push -u origin main

日常作業ループ

git status
git diff
git add -p              # 変更ハンク単位で確認しながら add
git commit -m "feat: 機能の説明"
git push

取り消し操作(破壊度が低い順)

git restore <file>           # ワーキングツリーの変更を破棄
git restore --staged <file>  # add を取り消し(ファイル本体は残る)
git commit --amend           # 直前コミットを修正(push 前のみ)
git revert <commit>          # 取り消しコミットを新規作成(共有後でも安全)

やってはいけないこと

  • 共有済みコミットへの git push --force(チーム全員の履歴が壊れる)
  • 確認なしの git reset --hard(コミット前の作業が消える)
  • .env / 秘密鍵 / 認証トークンのコミット(履歴に残ると除去が困難)
  • --no-verify での hook スキップ(lint / テスト失敗を握りつぶす)

次に読む