0.はじめに
対象者
- 普段Gitのcommit, push, pullを使っている人
伝えたいこと
- pullはfetchとmergeの組み合わせ
- mergeにはFast ForwardとAuto Mergeの2種類ある
- conflictの発生原因、解決方法
参考図書
目次
- Gitの概要
- ハンズオンのための環境構築
- fetchとmerge
- conflict
- Gitの便利な機能
- 付録
1. Gitの概要
Gitとは?
バージョン管理システム(Version Control System, VCS)。
Linuxカーネルのソースコード管理のために開発された。
2005年に開発された。
バージョン管理システムの種類
-
集中型バージョン管理システム
- リポジトリはサーバ上にある
- ネットワークに接続しないと利用できない
- Subversion, CVSなど
-
分散型バージョン管理システム
- リポジトリはサーバだけでなくローカル上にもある
- ネットワークに接続しなくても利用できる(commitなど)
- Gitなど
時代は集中型から分散型へ!!
2. ハンズオンのための環境構築
TortoiseGitのインストール
-
Git for Windows(v2.12)
https://git-for-windows.github.io/ -
TortoiseGit(v2.4)
https://tortoisegit.org/
※OSはWindows
リポジトリの作成
Aさん、Bさんがリモートリポジトリにアクセスするのを、再現できるようにする。
- ディレクトリを作成
remote/ :リモートリポジトリ
local-A/ : Aさんのローカル
local-B/ : Bさんのローカル
-
リモートリポジトリを作成(ベアリポジトリ)
remoteディレクトリに対して、コンテキストメニュから[Git Create repository here]を選択
[Make it bare]チェックをONにして、リポジトリを作成。 -
local-A, local-Bに対してGit Cloneする。
-
sample.txtという適当なファイルをlocal-Aディレクトリに配置して、commit, pushする。
-
local-Bに対してpullする
3. fetchとmerge
fetchとは?
リモートリポジトリから最新情報を取得する操作。
Let's Try
- local-Aとlocal-Bを同じ状態にする
- local-Aにcommit,pushする
- local-Bで[Show log]を実施
- [All branches]にチェックを入れて、ローカルとリモートのmasterブランチを比較。
確認項目
- fetchで最新情報が取得できる
- Gitのlogはローカルリポジトリの中身を見ているだけで、リモートにはアクセスしていない。
1個目のmerge(Fast Forward:早送り)
Let's Try
- local-Aとlocal-Bを同じ状態にする
- local-Aにcommit,pushする
- local-Bでfetch, mergeを実施
確認項目
- TortoiseGitのメッセージに[Fast-forward]と表示される
- 履歴グラフが枝分かれしていない。local-Aに対してのコミットが追加された(早送り)だけ。
- fetch, mergeの結果が、普段使っているpullの結果と同じ
merge(Fast Forward)の図
bugfixブランチをmasterブランチにマージ
↓
サルでもわかるGit入門 より引用
2個目のmerge(Auto merge)
Let's Try
- local-Aとlocal-Bを同じ状態にする
- local-Aにcommit,pushする(sample.txtの先頭行を修正)
- local-Bにcommitする(sample.txtの最終行を修正)
- local-Bでpullする
確認項目
- Merge Commitが追加される
- 履歴グラフが枝分かれしている(親が2個ある)
Gitは自動でmergeしてくれる!
merge(Auto merge)の図
bugfixブランチをmasterブランチにマージ
↓
サルでもわかるGit入門 より引用
4. Conflict
Conflictはいつ起こる?
同じファイルの同じ行が修正されたとき
⇒Gitがmergeするとき、どちらを採用すればよいか分からないとき
Let's Try
- local-Aとlocal-Bを同じ状態にする
- local-Aにcommit,pushする(sample.txtの先頭行を修正)
- local-Bにcommitする(sample.txtの先頭行を修正)
- local-Bでpullする
確認項目
- Conflictが発生する。以下のようなメッセージ。
- ファイルの中身に、[<<<<<<< HEAD]が追記されている。上側が元ファイルの内容。下側がpullした内容。
C#
<<<<<<< HEAD
Scala
=======
Object-C
>>>>>>> aba32016ef3946904f84e2a1390b37d115e3411f
C++
Conflictの解決方法
TortoiseGitMergeを使う。
Let's Try
- local-Bでconflictが発生している状態
- conflictが発生しているファイルのコンテキストメニュから[Edit Conflicts]を選択
- conflictしている行を選択して、コンテキストメニュの項目から、coflictを解決する。Mergedウィンドウに赤い行がなくなればOK.
- [Mark as resolved]ボタンを押す。Gitにconflictが解決したことを知らせる。
- local-Bでcommitする
確認項目
- コミットメッセージ欄に「Conflict」と記入される
Conflictが起きたときにしてはいけないこと
-
conflictを解決せずに[Mark as resolved]ボタンを押して、「<<<<<<< HEAD」がある状態でcommitする
-
commitするとき、自分が修正していないファイルをcommit対象からはずす(他のユーザが修正したmerge用のファイルかもしれない)
-
commitするとき、自分が修正中のファイルをcommitしない([stash save ]で差分がない状態にしてから、pullすべき)
メンバーにGit初心者がいるならば、conflictの扱いには注意すること。
「conflictが発生したら、何もしないで呼んでください」などの対応が必要。
Conflictが発生しないようにするには(自分の考え)
Fast ForwardなMergeが行われるようにする。
- 作業開始する前にはpullして、できるだけ最新なソースに対して修正する
- 同じファイルを修正しなくてもよいようなファイル設計にする(機能ごとにファイル分割など)
[Abort Merge]でConflict発生前の状態に戻すこともできる。
(差分がある場合は大丈夫?)
5. Gitの便利な機能
[Try] 差分を見たい
- コミット間の差分
- ブランチ間の差分
- 差分のあるファイルを出力[Export selection to]
- ファイルを選択して[Blame]. コミットのよる変更行がわかる。
1ファイルに対しての複数個所の修正を、複数のコミットに分けたい場合
- コミットの対象のファイルを選択
- コンテキストメニュから[Restore after commit]を選択
- 差分エディタで、コミット対象外の修正を削除する
- commit
- 上記の操作で取り消した修正が、元に戻る
コミットを取り消したいとき
pushする前に取り消したい
git resetを利用する。
pushした後に取り消したい
git revertを利用する. 打ち消すためのコミットが追加される。
コミット自体は消せない。
過去は変えられない!!
Rename前のログを見る
ファイルを選択してTortoiseGitの「Show log」したとき、Rename前のログが見られない。
以下、Rename以前のログを見る方法。
- Git Logウィンドウで、Statusが「Rename」のファイルを選択
- 右クリックメニュから「Show log before rename/copy」を選択
Git Bashの場合
git log --follow [filepath]
--follow
Continue listing the history of a file beyond renames (works only for a single file).
知っておいて欲しい機能
- git rename :ファイルの移動
- stash save:差分を一時的に保存(コミットしたくないけどプルしたいとき)
- git tag :コミットに目印をつけたいとき(リリース完了後など)
- git branch: 同時に複数の作業を行うとき
付録
Gitの開発フロー
- git-flow
- github-flow
現場に合った最適なフローを探しましょう!
[Try]Gitをコマンドで使ってみよう
Git Bashを利用