ここではGitの基本的な部分の説明しかしませんので、あしからず
目次
- Git 作業フロー
- 基本的なコマンド集
- 初期設定
- 変更の反映
- ブランチ操作
- 確認
Git 作業フロー
概要
- Branch : これから行う作業全体の内容を表すブランチを作ります
- Commit : あとで読み返す時にわかりやすいコミットを心がけます
- Push : 定期的にリモートに変更を送ります。小休憩の前に行うのがベストです
- Pull : 他の人の変更をローカルに取り込みます。競合が発生する場合もあります
- Merge : 複数のブランチを統合して、完成系に近づけます
基本的なコマンド集
初期設定
Git リポジトリを初期化する (init)
書式
git init
説明
新規リポジトリの作成をするときに使います。通常は .git という名前のディレクトリが作成されます。
$ # リポジトリの初期化
$ git init
Initialized empty Git repository in /path/to/dir/.git/
作成されるディレクトリの中身
.git
├── HEAD # 現在のブランチの情報
├── config # このリポジトリの設定
├── description # このリポジトリの説明
├── hooks/ # フックスクリプト
│ ├── applypatch-msg.sample*
│ ├── commit-msg.sample*
│ ├── post-update.sample*
│ ├── pre-applypatch.sample*
│ ├── pre-commit.sample*
│ ├── pre-push.sample*
│ ├── pre-rebase.sample*
│ ├── prepare-commit-msg.sample*
│ └── update.sample*
├── info/
│ └── exclude # このリポジトリで無視したいファイル
├── objects/ # Gitのバージョン管理オブジェクト
│ ├── info/
│ └── pack/
└── refs/ # ブランチやタグの参照情報
├── heads/
└── tags/
リポジトリの複製 (clone)
書式
git clone <url>
説明
リモートリポジトリ(共有リポジトリ)を作業者のパソコンの中に複製します
- url : リモートリポジトリが置いてある場所のURL
$ # リポジトリの複製
$ git clone https://github.com/username/repository
Cloning into 'repository'...
remote: Counting objects: 36, done.
remote: Total 36 (delta 0), reused 0 (delta 0), pack-reused 35
Unpacking objects: 100% (36/36), done.
Checking connectivity... done.
Git の設定の表示と変更 (config)
書式
git config [--global] <name> [<value>]
説明
- –global : ユーザのGitの設定を行う。globalオプションを指定しない場合は、リポジトリのGitの設定を行う。
- name : 値の名前
- value : 設定値
$ # ユーザ名とメアドの設定
$ git config --global user.name "My Name"
$ git config --global user.email "foo@bar.baz"
$ # ユーザ名の確認
$ git config --global user.name
My Name
--global
を指定して設定した場合は、~/.gitconfig に設定が書き込まれます。
上のコマンドを実行すると、.gitconfig ファイルには次のように変更が加えられます。
[user]
name = My Name
email = foo@bar.baz
リモートリポジトリを設定する (remote)
書式
git remote [-v]
: 登録されているリモートリポジトリの一覧を表示
git remote add <name> <url>
: リモートへの接続方法の追加
git remote rename <old> <new>
: リモート名を old から new に変更する
git remote set-url <name> <newurl>
: リモートのURLの変更
$ # リモートリポジトリの登録
$ git remote add origin https://github.com/usr/repository
$ # リモートのURLを変更
$ git remote set-url origin https://github.com/usr/repository2
$ # リモート名とそのURLの確認
$ git remote -v
origin https://github.com/usr/repository2.git (fetch)
origin https://github.com/usr/repository2.git (push)
変更の反映
下矢印が変更の取り込み、上矢印が変更の追加を表しています
GitHub
(Remote_Repository) # リモートリポジトリ
| | ∧
| | |
----------|------|-------|----------
PC | | |
| fetch| |push
| ∨ |
(Local_Repository) # ローカルリポジトリ
| | ∧
pull| | |commit
| | |
| | (Index) # インデックス
| | ∧
| merge| |add
∨ ∨ |
(Working_Directory) # 作業ディレクトリ
pull は fetch と merge をまとめて行います
- add, commit, push, pull, fetch, merge
単語 | 説明 |
---|---|
Remote Repository (リモートリポジトリ) | チーム全員で共有するリポジトリ |
Local Repository (ローカルリポジトリ) | 作業者のマシン上にあるリポジトリ |
Working Directory (作業ディレクトリ) | 現在の作業ディレクトリ |
Index (インデックス) | ローカルリポジトリへ反映する変更を一時的にためておく場所 |
以後、リモートリポジトリをリモート、ローカルリポジトリをローカルと省略して書く場合があります
変更をインデックスに登録 (add)
書式
git add <file> [<file>...]
説明
- file : インデックスに登録するファイル名
$ # ファイルをインデックスに追加
$ git add test.txt
$ # 全てのファイルを追加
$ git add *
$ # フォルダ下にある全てのファイルを追加
$ git add dir/
変更をローカルリポジトリに反映 (commit)
ブランチの様子
commit
A---B---C---D => A---B---C---D---E
∧ ∧
* master * master
書式
git commit [--amend] [-a] [-m <message>]
説明
- –amend : 直前のコミットをやり直す
- -a : バージョン管理をしている(追跡をしている)すべてのファイルをコミット
- -m
: コミットメッセージを追加する。あとで読み返すときにわかるように、必ず何か書くこと
$ # インデックスにあるファイルをコミット
$ git commit -m 'your message'
[master 41f79d5] your message
1 file changed, 3 insertion(+)
$ # 追跡している全てのファイルをコミット (addもまとめて行う)
$ git commit -am 'your message'
$ # 直前のコミットのコメントを書き換える
$ git commit --amend -m 'fixed message'
$ # ファイルの登録漏れの修正
$ git add test.txt
$ git commit --amend -m 'your message'
リモートに変更を送る (push)
ブランチの様子
remote remote
A---B A---B---C---D
∧ ∧
origin/master origin/master
push
-------------------------- => --------------------------------
local local
A---B---C---D A---B---C---D
∧ ∧
* master * master
書式
git push [--all] [--delete] [<repository> [<ref>]]
説明
- –all : 全てのブランチをpushする
- –delete : リモートリポジトリのブランチの削除
- repository : push先のリポジトリ(デフォルトは origin )
- ref : ブランチ名
$ # リモートのoriginに変更を送る
$ git push origin master
$ # いつもpushするリモートに設定する
$ git push --set-upstream origin master
$ # リモートリポジトリに変更を送る(--set-upstream 設定後)
$ git push
$ # 新規に作成したブランチを送る
$ git push origin new-branch
$ # リモートのブランチを削除
$ git push --delete origin new-branch
$ # もしくは
$ git push origin :new-branch
リモートの変更を取得してマージする (pull)
ブランチの様子
remote remote
A---B---C---D A---B---C---D
∧ ∧
origin/master origin/master
-------------------------------- pull --------------------------------
local => local
A---B A---B---C---D
∧ ∧
* master * master
書式
git pull [<repository> [<ref>]]
説明
fetchとmergeを同時に行う(pull = fetch + merge)
- repository : pull先のリポジトリ(デフォルトは origin )
- ref : ブランチ名
$ # リモートのoriginの変更をpullする
$ git pull origin master
$ # リモートのoriginをいつもpullするリモートに設定する
$ git pull --set-upstream origin master
$ # リモートの変更を取得してマージ(--set-upstream 設定後)
$ git pull
$ # 指定したブランチ「topic」をpullする
$ git push origin topic
$ # リモートのブランチ「foo」を取得して、ローカルにブランチ「foo-branch」を作成
$ git pull origin foo:foo-branch
リモートの変更を取得する (fetch)
ブランチの様子
remote remote
A---B---C---D A---B---C---D
∧ ∧
origin/master origin/master
----------------------------- fetch -----------------------------
local => local
C---D < FETCH_HEAD
/
A---B A---B
∧ ∧
* master * master
書式
git fetch [<repository> [<ref>]]
説明
リモートの変更を取得して、FETCH_HEAD という名前のブランチを作成します。 merge する場合は FETCH_HEAD を現在のブランチに取り込みます。
- repository : fetch先のリポジトリ(デフォルトは origin )
- ref : ブランチ名
$ # リモートの変更を取得
$ git fetch
$ git log HEAD..FETCH_HEAD # 現在のブランチのHEADから、フェッチしたブランチのログを確認
$ git diff HEAD..FETCH_HEAD # 現在のブランチのHEADから、フェッチしたブランチの差分を確認
$ git merge FETCH_HEAD # 確認後、現在のブランチにマージする
コミットのリセット (reset)
ブランチの様子
reset
A---B---C---D => A---B---C
∧ ∧
* master * master
書式
git reset [--mixed | --hard | --soft] <commit>
説明
- –mixed : インデックスの登録を取り消す。引数がファイル名の場合はこのモードになる
- –hard : 作業ディレクトリもインデックスも破棄して、指定したコミットまで戻す
- –soft : コミットだけを取り消す。作業ディレクトリとインデックスはそのまま
- commit : commit番号(7桁の英数字)または、HEADからの相対参照
$ # ファイルをインデックスから外す
$ git reset test.txt
$ # または
$ git reset --mixed test.txt
$ # 直近から1つのコミットを取り消す
$ git reset HEAD^
$ # または
$ git reset --soft HEAD^
$ # 2つ前のコミットまで、作業を巻き戻す
$ git reset --hard HEAD~2
ブランチ操作
概要
Gitは変更の枝分かれの数だけ、ブランチを持っています
topic
∨
D---G
/
A---B---C---E---F
∧
* master
この作業ツリーには master と topic の二つのブランチが存在します。
ブランチ名の前に*
が付いているのは、現在作業しているブランチを示しています。
#HEAD^ と HEAD~n について
上の図の master について、最新のコミット「F」は HEAD
で参照できます。
1つ前のコミット「E」は HEAD~
で参照できます。(またはHEAD^
)
nつ前のコミットは HEAD~n
(nは整数)で参照できます。
補足
zsh の extended_glob オブションが有効な場合、
HEAD^
とやっても期待通りの結果は得られません。エスケープが必要です
$ git show HEAD^
zsh: no matches found: HEAD^
これは「ファイル名が HEAD から始まるが、その次が文字の終端ではないファイルと一致する」 という展開が発生するからです。
$ ls
head head.txt head100 tail
$ ls head^
head.txt head100
HEAD と @
コミットを参照するときに、@
を使うと HEAD
に変換されます
HEAD~2
と @~2
の参照は同じです
補足
FETCH_HEAD
を FETCH_@
と省略するのはダメです
–
ブランチを操作する (branch)
ブランチの様子 (ブランチ作成の例)
topic
branch ∨
A---B---C => A---B---C
∧ ∧
* master * master
書式
git branch
: 全てのローカルブランチを表示する
git branch [-m | -d] <branch_name>
説明
- オプションなし : 新しいブランチの作成
- -m : 現在のブランチ名を変更
- -d: ブランチの削除
git branch <branch_name> <start_point>
説明
- branch_name : 新しいブランチの名前
- start_point : 指定したコミットを起点としたブランチを作成する
$ # ブランチの確認
$ git log --oneline --decorate --graph
* e0ef2c4 (HEAD, master) latest
* ef06c5c major fix
* a8e5f07 again, minor fix
* 05bf6c1 minor fix
* 54e47ac first commit
$ # ブランチの作成
$ git branch new-branch
$ # 指定したコミットを起点にブランチを作成
$ git branch set-start-branch HEAD~2
$ # ブランチの確認
$ git log --oneline --decorate --graph
* e0ef2c4 (HEAD, master, new-branch) latest # new-branch が追加せれた
* ef06c5c major fix
* a8e5f07 (set-start-branch) again, minor fix # set-start-branch が追加された
* 05bf6c1 minor fix
* 54e47ac first commit
$ # ブランチの一覧を表示
$ git branch
* master
new-branch
set-start-branch
作業ブランチを切り替える (checkout)
ブランチの様子
topic * topic
∨ ∨
D---F checkout D---F
/ => /
A---B---C A---B---C
∧ ∧
* master master
書式
git checkout <branch>
: 作業ブランチを指定したブランチに切り替える
git checkout -b <new_branch> [<startpoint>]
説明
- -b : 指定したブランチが存在しない場合は、作成する
- start_point : 指定したコミットを起点としたブランチを作成する
$ # ブランチの切り替え
$ git checkout other-branch
$ # ブランチの作成
$ git checkout -b new-branch
git checkout -b new-branch
は、ブランチの作成 git branch new-branch
と
ブランチの切り替え git checkout new-branch
をまとめて行ってくれるので、
ブランチの作成によく使われます。
他のブランチの変更内容をマージする (merge)
ブランチの様子
* topic * topic
∨ ∨
D---F merge D---F---G
/ => / /
A---B---C---E A---B---C---E
∧ ∧
master master
書式
git merge [-m <message>] <branch>
説明
- -m : マージのコミットのメッセージを指定する
- branch : 取り込むブランチ名
$ # master ブランチの変更を、現在のブランチに取り込む
$ git merge master
$ # fetchしてできたブランチ FETCH_HEAD をmergeする
$ git merge FETCH_HEAD
競合について
例えば、other-branch の test.txt ファイルと master の test.txt ファイルで別々の内容を加えたとします。
master:test.txt other-branch:test.txt
----------------- -----------------------
item1 other-list1
item2 other-list2
この状態で、master に other-branch をマージすると競合が発生します。
具体的には、次のように表示されます
$ # mergeをする際に、競合が発生した場合
$ git merge other-branch
Auto-merging test.txt
CONFLICT (content): Merge conflict in test.txt
Automatic merge failed; fix conflicts and then commit the result.
$ # ファイルの状態を確認
$ git status
On branch master
Your branch and 'origin/master' have diverged.
and have 1 and 1 different commit each, respectively.
Unmerged paths:
(use "git add <file>..." to mark resolution)
both modified: test.txt
no changes added to commit (use "git add" and/or "git commit -a")
$ # test.txt の競合箇所がわかるように書き変わっているのを確認
$ cat test.txt
<<<<<<< HEAD
item1
item2
=======
other-list1
other-list2
>>>>>>> other-branch
$
エディタで競合しているファイルを開いて、編集します。 今回は、両方の変更を採用したいので、test.txt の中身を次のように書き換えます。
item1
item2
other-list1
other-list2
このとき、境界線である <<<<<<<
, =======
, >>>>>>>
は削除します
修正が完了したら、インデックスに追加してコミットします。
$ git add text.txt
$ git commit
[master bed8323] Merge branch 'other-branch'
$ git push
外部ツールを使って競合を解決する (mergetool)
git mergetool [-t <tool>] [<file>...]
説明
競合が発生している際に、外部ツールを使って競合を解決します
- -t : 使用する外部ツールを指定する
- file : 競合中のファイルを指定する(省略した場合は、全ての競合中のファイルが選ばれる)
$ git mergetool -t vimdiff
# vimdiff が起動する
vimで変更を加える時は i
を押して、編集して、<Esc>
で書き込みモードから離れます。
編集の保存は :w
と入力します。
全てのウィンドウを閉じるには :qa
と入力します
ブランチの起点を変更する (rebase)
ブランチの様子
* topic * topic
∨ ∨
D---F---G rebase D'--F'--G'
/ => /
A---B---C---E A---B---C---E
∧ ∧
master master
書式
git rebase <upstream> [<branch>]
説明
ブランチの起点(分岐元)を変更します
- upstream : ブランチの分岐元のコミットやブランチを指定する
- branch : rebase対象のブランチ名(省略した場合は、現在のブランチ)
$ # 現在のブランチを、masterブランチの最新コミットから分岐したように変更
$ git rebase master
他のブランチのコミットを取り込む (cherry-pick)
ブランチの様子
* topic * topic
∨ ∨
D---F cherry-pick D---F---G'--H'
/ => /
A---B---C---E---G---H A---B---C---E---G---H
∧ ∧
master master
書式
git cherry-pick <commit>
説明
- commit : 取り込み対象のコミット
$ # コミット b75ffb1 を現在のブランチに取り込む
$ git cherry-pick b75ffb1
コミット番号は、git log --oneline <branch>
などで確認できます
確認
ファイルの状態を表示 (status)
git status [-s]
説明
未追跡のファイル、修正が加えられたファイル、インデックスに登録されたファイルなどの情報が見られる
- -s (–short) : 短いフォーマットで表示する。ファイルが多い場合に確認しやすい
$ # ファイルの状態を確認
$ git status
On branch master # 現在のブランチの状態
Your branch is ahead of 'origin/master' by 3 commits.
(use "git push" to publish your local commits)
Changes to be committed: # インデックスの登録されているファイル
(use "git reset HEAD <file>..." to unstage)
new file: 登録済みファイル
Unmerged paths: # 競合中のファイル
(use "git add/rm <file>..." as appropriate to mark resolution)
both modified: 競合中のファイル
Changes not staged for_commit: # インデックスに追加されていないファイル
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: 未登録ファイル
Untracked files: # 追跡していないファイル
(use "git add <file>..." to include in what will be committed)
Gitのバージョン管理外のファイル
no changes added to commit (use "git add" and/or "git commit -a")
Untracked files に追跡していないファイルを表示させないようにするには、 .gitignore に無視するファイルを追加(作成)します。
.gitignore
*.o # 拡張子が .o で終わるファイルは無視
dir/ # 指定したディレクトリ以下の全てのファイルを無視
!dir/template # 先頭に ! を加えて、無視していたファイルを無視しないようにする
git status -s
での表示形式について、
1文字目はインデックスの状態、2文字目は作業ディレクトリの状態を表しています。
先頭の大文字英字には、次のような意味があります。
文字 | 意味 |
---|---|
(なし) | 変更なし |
M | 変更 (modify) |
A | 追加 (add) |
D | 削除 (delete) |
R | 名前変更 (rename) |
C | 複製 (clone) |
U | 競合 (unmerged) |
以下に具体例を示します
$ # ファイルの状態をシンプルな表示で確認
$ git status -s
A newfile.txt # インデックスに追加済みの新規ファイル
M changefile.txt # 作業ディレクトリ上の新しい変更
M addfile.txt # インデックスに追加済みの変更
MM addchangefile.txt # インデックスに追加後、作業ディレクトリで新たな修正が加えられたファイル
R file.txt -> renamedfile.txt # インデックスに追加済みの変更(ファイル名の変更)
?? untrackedfile.txt # バージョン管理外のファイル
履歴を表示する (log)
git log [--<options>] [-<n>] [<range>] [<file>]
説明
- –oneline : コミットメッセージの1行目だけを表示する
- –graph : グラフを表示する。ブランチの分岐やマージを確認するのに便利
- –decorate : HEAD, Tag, リモートブランチのHEADの情報も合わせ表示する
- –stat : コミットの変更内容の統計情報を表示する
- -n : 直近のn件のコミットを表示する(nは整数)
- range : since から until までの log を
since..until
と指定して表示する
$ # コミットログの一覧
$ git log
$ # branch1とbranch2を比較して、branch2にのみ存在するコミットの、1行目のメッセージを表示する
$ git log --oneline master..other-branch
$ # source treeのブランチの出力を真似る
$ git log --oneline --decorate --graph
# グラフの例
* 52037cb (HEAD, github/master, master) Add TODO
* 7f12aba Merge pull request #15 from committer/master
|\
| * d255dbc (github/camera-feature) created Foo.cs
| * 95a90ec Add Foo.cs
* | 15740d7 Create diagram
* | a9863b7 Rename new block. 'block' -> 'block(new)'
|/
* 41963e2 Merge branch 'master' of https://github.com/team/repo
$ # 片方のブランチにしかないコミットを表示
$ # この例では、other-branch にあって、master にはないコミットの一覧
$ git log master..other-branch
差分を表示する (diff)
git diff [--cached]
説明
変更の差分を表示します
- –cached : インデックスと特定のコミットの差分を表示する
$ # 作業ディレクトリと最新のコミットとの差分を表示
$ git diff
$ # インデックスと最新のコミットとの差分を表示
$ git diff --cached
$ # 作業ディレクトリと指定のコミットとの差分を表示
$ git diff 41963e2
$ # 2つのコミットの差分を表示
$ git diff 41963e2 7f12aba
$ # または
$ git diff 41963e2..7f12aba
$ # 2つのブランチの差分を表示
$ git diff master..FETCH_HEAD
コミットを表示する (show)
git show [--oneline] <commit>
説明
指定したコミット情報を表示します
- –oneline : コミットメッセージの1行目だけを表示
$ # 最新のコミットの情報を表示
$ git show HEAD
$ # 指定したコミットの情報を表示
$ git show 41963e2
$ # 直近から3件のコミットの情報を表示
$ git show -3
リポジトリの操作履歴の確認 (reflog)
git reflog
説明
リポジトリの操作履歴の確認
$ # コミットログを確認
$ git log --oneline
41963e2 third commit
63fc109 second commit
a178120 first commit
$ # 2つ前のコミットまで戻す
$ git reset HEAD~2
$ # 操作履歴の確認
$ git reflog
f287e54 HEAD@{1}: reset: moving to HEAD~2
41963e2 HEAD@{2}: commit: third commit
63fc109 HEAD@{3}: commit: second commit
a178120 HEAD@{4}: commit: first commit
...
$ # 先ほどのresetを取り消す
$ git reset HEAD@{2}
Gitコマンドのヘルプ (help)
git help <command>
説明
gitのコマンドの使い方を確認します
$ git help checkout
# manが起動する