Git

社内Git勉強会

本勉強会の目的

:ghost: Gitよくわからん… 

:alien: Gitスコシワカル

Gitのドキュメントを読む足がかりになれればという位置づけ


今日の内容

  • 状態
  • ブランチ
  • HEAD
  • origin
  • git コマンドとの付き合い方
  • おまけTips(git stash)

Gitの誕生

誕生のきっかけ

Linuxカーネルの開発において新しいVCSが必要になった。 :penguin:


3つのエリアとそれぞれの状態を知ろう

  • 作業ディレクトリ(Working Directory)
  • ステージングエリア
  • .gitディレクトリ(Repository)

作業ディレクトリ

  • 私達が実際にファイルを追加・修正したりするときのエリア。ファイルはuntracked/trackedのどちらかの状態。
  • trackedの場合modified/unmodifiedの状態を取る。
  • 別名ワーキングツリーとも

ステージングエリア

  • git addするとここに配置される。
  • git commit時にはこのステージングエリアにあるファイルが対象になる。
  • 別名インデックスとも。
  • このエリアに追加されるとステージ済みの状態(staged/unstaged)

.gitディレクトリ(Repository)

  • プロジェクトのためのメタデータなどが格納されている。
  • git commitをするとその情報がここに蓄積される。
  • このエリアに追加されるとコミット済み

https://git-scm.com/book/en/v2/images/lifecycle.png


ブランチ

ブランチの前に… git におけるcommitとは?

Gitはデータをミニ・ファイルシステムのスナップショットの集合のように考えます。 Gitで全てのコミット(訳注:commitとは変更を記録・保存するGitの操作。詳細は後の章を参照)をするとき、もしくはプロジェクトの状態を保存するとき、Gitは基本的に、その時の全てのファイルの状態のスナップショットを撮り(訳者注:意訳)、そのスナップショットへの参照を格納するのです。 効率化のため、ファイルに変更が無い場合は、Gitはファイルを再格納せず、既に格納してある、以前の同一のファイルへのリンクを格納します。 Gitは、むしろデータを一連のスナップショットのように考えます。

ブランチとは?
ブランチはある時点のコミットを示すポインタ。


https://git-scm.com/book/en/v2/images/branch-and-history.png


ブランチの種類

  • リモートブランチ
  • ローカルブランチ
    • リモート追跡ブランチ
    • ローカル追跡ブランチ
    • (通常の)ローカルブランチ

リモートブランチ


リモートリポジトリにあるブランチ

  • リモート にあるので普段これを触ったりはしない。
  • 私達はpush/fetchを通じてしか操作できない。

ローカルブランチ


(通常の)ローカルブランチ

$ git checkout foo master
  • 他のローカルブランチ区別するために「通常の」と付けている
  • このあと紹介する2つのローカルブランチの特性が無いブランチ

リモート追跡ブランチ

  • ローカル に作成される。
  • 最初のcloneかfetchの度、リモートブランチの状態を保存してる。
  • リモートブランチの状態を知るには、ローカルにあるリモート追跡ブランチを参照することになる。(リモートブランチとのつながりを持っている)
  • remotes/<remote>/<branch>という名前で作られる。(省略形は <remote>/<branch>)
  • このブランチへのコミットは不可

ローカル追跡ブランチ

  • ローカルに作成される。
  • リモートブランチへのコミットを発行するためのブランチ。
  • 通常のローカルブランチとほぼ同じだが唯一の違いは、リモート追跡ブランチとつながっている事。
  • このブランチへのコミットは可能

ローカル追跡ブランチの作成方法をみてもリモート追跡ブランチとつながりを持っていることが見て取れる。

$ git checkout -b <local_branch>  <remote>/<branch>
  • 既に手元にあるローカルブランチを、リモートブランチの取り込み先に設定したい場合git branch -u <remote>/<branch>

HEAD ?

  • HEADは作業しているブランチを指すポインタ
  • git checkout <branch>で HEADが指すブランチが変わる。

$ git checkout master

https://git-scm.com/book/en/v2/images/head-to-master.png


$ git checkout testing

https://git-scm.com/book/en/v2/images/head-to-testing.png


$ git commit # 87ab2
$ git checkout master

https://git-scm.com/book/en/v2/images/checkout-master.png


  • 現在のブランチの最新コミットを指す。
  • 現在操作しているリビジョンのSHA-1ハッシュ(commit id)が必要な場面でHEADを使える。
  • パラメータを指定しない場合のデフォルト値になる
  • 相対的な指定もできる。
  • HEADのエリアスとして@が使える
$ git show HEAD    # 現在の最新コミット
$ git show HEAD^   # 現在の最新コミットの1つ前
$ git show HEAD~   # 現在の最新コミットの1つ前
$ git show HEAD^1  # 現在の最新コミットの1つ前
$ git show HEAD~1  # 現在の最新コミットの1つ前

$ git show HEAD^^^ # 現在の最新コミットの3つ前
$ git show HEAD~~~ # 現在の最新コミットの3つ前
$ git show HEAD~3  # 現在の最新コミットの3つ前

上記の通り^(キャレット)または~(チルダ)で相対指定が可能。

ただし、^数字(例えばHEAD^2)と入力した場合は注意が必要となる。HEADがマージコミットで親が2つ持つ場合等はHEAD^数値は親コミットの指定に使われる。
~はマージコミットでは常に最初の親を参照する。

$ git show HEAD^2~2 # 2番目の親の2つ前

originとは?

  • リモートリポジトリからgit cloneした時にgitがデフォルトでつける名前。読み込み用と書き込み用がある。
  • 名前を変更することもできる。
  • git remote -vで確認できる。
  • 複数のリモートリポジトリを登録することもできる。
  • 何も特別意味のあるものではない、リモート先の情報を参照するための変数名のようなイメージ
$ git push  origin     master
#           <リモート先>  <ブランチ名>

git コマンドとの付き合い方

コマンド+オプションを覚えるのも打鍵するのも大変なので、エリアスを活用しよう。

$ vim ~/.gitconfig

例えば

git addの取り消し、git reset HEADは覚えにくいと感じたら

git unstage <filename>

git commit -mが長いと感じたら

git save <message>

git branchで常にたくさんの情報(-a, -vv)を観たいとおもったら

git branches

もしくはGitクライアントを利用する。(sourcetree, totoise, tig...)


Tips


Stash 作業をポケットに一時退避

使えるケース:
ある作業中により優先度の高い作業を振られたが、いまの作業はコミットできないし、破棄もしたくないような場合。

git stash で今の作業を一時退避できる。

  • ステージングエリアと作業ディレクトリの現在の状態を保存し
  • 作業ディレクトリをリセットする
$ git stash save <任意の名前(省略可)>
# 注意点として untrackedなファイルは対象とならないので先に`git add -A`をしておくのがおすすめ。

この時点で最後のコミットした時点に戻ります。
下記で一時保存した内容を確認できます。

$ git stash list

ここでブランチを切って優先度の高い対応を行う。
コミット後元いたブランチに戻って次のコマンドでsaveした内容を復活。且つリストからも削除

$ git stash pop

参考