【社内勉強会】Git初心者から卒業するための準備(2017/03/28)


0.はじめに


対象者

  • 普段Gitのcommit, push, pullを使っている人

伝えたいこと

  • pullはfetchとmergeの組み合わせ
  • mergeにはFast ForwardとAuto Mergeの2種類ある
  • conflictの発生原因、解決方法

参考図書

Gitが、おもしろいほどわかる基本の使い方33


目次

  1. Gitの概要
  2. ハンズオンのための環境構築
  3. fetchとmerge
  4. conflict
  5. Gitの便利な機能
  6. 付録

1. Gitの概要


Gitとは?

バージョン管理システム(Version Control System, VCS)。
Linuxカーネルのソースコード管理のために開発された。
2005年に開発された。


バージョン管理システムの種類

  • 集中型バージョン管理システム

    • リポジトリはサーバ上にある
    • ネットワークに接続しないと利用できない
    • Subversion, CVSなど
  • 分散型バージョン管理システム

    • リポジトリはサーバだけでなくローカル上にもある
    • ネットワークに接続しなくても利用できる(commitなど)
    • Gitなど

時代は集中型から分散型へ!!


2. ハンズオンのための環境構築


TortoiseGitのインストール

※OSはWindows


リポジトリの作成

Aさん、Bさんがリモートリポジトリにアクセスするのを、再現できるようにする。

  1. ディレクトリを作成
remote/ :リモートリポジトリ
local-A/ : Aさんのローカル
local-B/ : Bさんのローカル
  1. リモートリポジトリを作成(ベアリポジトリ)
    remoteディレクトリに対して、コンテキストメニュから[Git Create repository here]を選択
    [Make it bare]チェックをONにして、リポジトリを作成。

  2. local-A, local-Bに対してGit Cloneする。

  3. sample.txtという適当なファイルをlocal-Aディレクトリに配置して、commit, pushする。

  4. local-Bに対してpullする


3. fetchとmerge


fetchとは?

リモートリポジトリから最新情報を取得する操作。

Let's Try

  1. local-Aとlocal-Bを同じ状態にする
  2. local-Aにcommit,pushする
  3. local-Bで[Show log]を実施
  4. [All branches]にチェックを入れて、ローカルとリモートのmasterブランチを比較。

確認項目

  • fetchで最新情報が取得できる
  • Gitのlogはローカルリポジトリの中身を見ているだけで、リモートにはアクセスしていない。

1個目のmerge(Fast Forward:早送り)

Let's Try

  1. local-Aとlocal-Bを同じ状態にする
  2. local-Aにcommit,pushする
  3. 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

  1. local-Aとlocal-Bを同じ状態にする
  2. local-Aにcommit,pushする(sample.txtの先頭行を修正)
  3. local-Bにcommitする(sample.txtの最終行を修正)
  4. local-Bでpullする

確認項目

  • Merge Commitが追加される
  • 履歴グラフが枝分かれしている(親が2個ある)

Gitは自動でmergeしてくれる!


merge(Auto merge)の図

bugfixブランチをmasterブランチにマージ

サルでもわかるGit入門 より引用


4. Conflict


Conflictはいつ起こる?

同じファイルの同じ行が修正されたとき
⇒Gitがmergeするとき、どちらを採用すればよいか分からないとき

Let's Try

  1. local-Aとlocal-Bを同じ状態にする
  2. local-Aにcommit,pushする(sample.txtの先頭行を修正)
  3. local-Bにcommitする(sample.txtの先頭行を修正)
  4. local-Bでpullする

確認項目

  • Conflictが発生する。以下のようなメッセージ。
  • ファイルの中身に、[<<<<<<< HEAD]が追記されている。上側が元ファイルの内容。下側がpullした内容。
sample.txt
C#
<<<<<<< HEAD
Scala
=======
Object-C
>>>>>>> aba32016ef3946904f84e2a1390b37d115e3411f
C++

Conflictの解決方法

TortoiseGitMergeを使う。

Let's Try

  1. local-Bでconflictが発生している状態
  2. conflictが発生しているファイルのコンテキストメニュから[Edit Conflicts]を選択
  3. conflictしている行を選択して、コンテキストメニュの項目から、coflictを解決する。Mergedウィンドウに赤い行がなくなればOK.
  4. [Mark as resolved]ボタンを押す。Gitにconflictが解決したことを知らせる。
  5. 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ファイルに対しての複数個所の修正を、複数のコミットに分けたい場合

  1. コミットの対象のファイルを選択
  2. コンテキストメニュから[Restore after commit]を選択
  3. 差分エディタで、コミット対象外の修正を削除する
  4. commit
  5. 上記の操作で取り消した修正が、元に戻る

コミットを取り消したいとき

pushする前に取り消したい

git resetを利用する。

pushした後に取り消したい

git revertを利用する. 打ち消すためのコミットが追加される。
コミット自体は消せない。
過去は変えられない!!


Rename前のログを見る

ファイルを選択してTortoiseGitの「Show log」したとき、Rename前のログが見られない。
以下、Rename以前のログを見る方法。

  1. Git Logウィンドウで、Statusが「Rename」のファイルを選択
  2. 右クリックメニュから「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-log Documentation


知っておいて欲しい機能

  • git rename :ファイルの移動
  • stash save:差分を一時的に保存(コミットしたくないけどプルしたいとき)
  • git tag :コミットに目印をつけたいとき(リリース完了後など)
  • git branch: 同時に複数の作業を行うとき

付録


Gitの開発フロー

  • git-flow
  • github-flow

現場に合った最適なフローを探しましょう!


[Try]Gitをコマンドで使ってみよう

Git Bashを利用