Table of Contents

モチベーション

Repositoryを用意する

ローカルリポジトリから始める

リモートリポジトリから始める

  1. GitHubにSSH公開鍵を登録しておく
    1. cd ~/.ssh
    2. ssh-keygen -t rsa -b 4096で鍵作成
    3. chmod 600 <秘密鍵へのパス>
    4. パスフレーズを設定したなら
      1. ssh-add <秘密鍵へのパス>で秘密鍵をSSHエージェントに登録
      2. ssh-add -lでSSHエージェントに秘密鍵が登録されたことを確認
    5. pbcopy < <公開鍵へのパス>で公開鍵をクリップボードにコピー
    6. SSH and GPG keysNew SSH keyに公開鍵をコピペ
    7. ~/.ssh/configに接続先を登録 Host <nickname> HostName github.com IdentityFile <秘密鍵へのパス> User git
    8. ssh -T <nickname>で接続確認
      • Hi XXX! You've successfully authenticated, but GitHub does not provide shell access.と言われれば優勝
    9. rm <公開鍵へのパス>で公開鍵を削除しておく
  2. git clone git@github.com:<repository>.git <directory>
    • <directory> : ローカルリポジトリとしたいディレクトリへのパス
    • <directory>内に.gitという隠しフォルダが作成される.Gitの諸々は.gitで管理されることになる.

Repositoryの初期設定をする

ユーザ情報を設定する

  1. git config --global user.name "<username>"
    • ローカルマシン内のすべてのlocal repositoryに触れるユーザを<username>に設定する.
    • この設定情報は~/.gitconfigに保存される.
  2. Local repositroy内でgit config --local user.name "<username>"
    • Local repositoryでの作業は<username>によって行われたものとしてログされていく.
    • git config --localにより設定したものは.git/configに保存される.
      • globalとlocalをどっちも設定している場合は,localの設定が優先される.
  3. 同じ要領で,git config --global/local user.emailでメールアドレスを登録する.

デフォルトのエディタやMerge tool, Diff toolを設定する

オリジナルのサブコマンドを設定する

[alias]
	history = log --graph --abbrev-commit --decorate --format=format:'%C(bold blue)%h%C(reset) - %C(bold green)(%ar)%C(reset) %C(white)%s%C(reset) %C(dim white)- %an%C(reset)%C(bold yellow)%d%C(reset)' --all

設定値の確認

Gitで管理したくないファイルを指定する

リモートリポジトリにはニックネームが付いている

リモートリポジトリには,ニックネームがついている.例えば,cloneしてきたローカルリポジトリにて,git config -lまたはgit remote -vを実行すると,以下のように,リモートリポジトリがoriginと名付けられていることが確認できる.

# git config -l でconfigを直接見る
remote.origin.url=git@github.com:<ユーザ名>/<リポジトリ名>.git
remote.origin.fetch=+refs/heads/*:refs/remotes/origin/*

# git remote -v でリモートリポジトリ一覧をみる
origin	git@github.com:<ユーザ名>/<リポジトリ名>.git (fetch)
origin	git@github.com:<ユーザ名>/<リポジトリ名>.git (push)

一方,git initで作成したローカルリポジトリに,任意のリモートリポジトリのニックネームを設定するには,git remote add <nickname> git@github.com:<user>/<repository>.gitを実行する.

ここで設定された/されているリモートリポジトリのニックネーム(たとえばoriginなど)は,git push origin mastergit pull origin masterなどのコマンドで利用される.

GitHubのレポジトリにHTTPSではなくSSHを使ってアクセスするように変更する

GitHubは2021年8月13日以降,パスワード(HTTPS)を使ったレポジトリへのアクセスを禁止する

GitHubにpushしたときに,GitHubから”You recently used a password to access the repository at “という内容のメールが飛んできた場合,<repository>へのアクセス方法がSSHではなくHTTPSになっている.

git remote -vすると,以下のようにhttpsから始まるリモートリポジトリが登録されていることが確認できる.

origin  https://github.com/<user>/<repository>.git (fetch)
origin  https://github.com/<user>/<repository>.git (push)

SSHを使ったアクセスに変更するには,git remote set-url origin git@github.com:<user>/<repository>.gitを実行し(git@github.comの部分は自分のsshの設定による.sshの設定についてはリモートリポジトリから始めるを参照),git remote -vすると,以下のように設定され,以後はSSHによるアクセスとなる.

origin	git@github.com:<user>/<repository>.git (fetch)
origin	git@github.com:<user>/<repository>.git (push)

コミットのいろいろな呼ばれ方

ブランチのいろいろな呼ばれ方

originが以下のようなブランチを持っているとすると,

master
branch1
branch2

git cloneにより,以下のようなブランチがローカルリポジトリにつくられる.

master
origin/master
origin/branch1
origin/branch2

リモートブランチをリモート追跡ブランチに取り込む

特定のコミットをカレントブランチに取り込む

      E---F---G dev
     /
A---B---C---D master

git checkout master & git merge dev

      E---F---G dev
     /         \
A---B---C---D---H master
      C---D---E dev
     /
A---B master

git checkout master & git merge dev

      C---D---E dev,master
     /
A---B 

リモートブランチをカレントブランチに取り込む

特定のコミットに移動する

カレントブランチの状態を確認する

変更したものをとりあえずひとまとめにする

変更を確定する

あるコミット時点のファイルをみる

変更履歴(コミットログ)をみる

差分をみる

特定のコミットをカレントブランチに反映させる

枝を付け替える

git rebase <start> <end>

git rebase -i <start> <end>

git rebase --onto <target> <start> <end>

特定のブランチをリモート追跡ブランチとリモートブランチに反映する

変更を戻す

git reset

# 初期状態

B <- HEAD,インデックス,ワーキングツリー
|
A


# ファイルを修正するとワーキングツリーが進む

  <- ワーキングツリー
|
B <- HEAD,インデックス
|
A


# git add により,インデックスが進む

  <- ワーキングツリー,インデックス
|
B <- HEAD 
|
A


# ファイルを修正するとワーキングツリーが進む

  <- ワーキングツリー 
|
  <- インデックス
|
B <- HEAD 
|
A

# git reset --soft HEAD
# HEADがHEADに移動する(この場合は何も起きない)

  <- ワーキングツリー 
|
  <- インデックス
|
B <- HEAD 
|
A


# git reset --soft HEAD^
# HEADがHEAD^に移動する

  <- ワーキングツリー 
|
  <- インデックス
|
B 
|
A <- HEAD 


# git reset HEAD
# HEADとインデックスがHEADに移動する

  <- ワーキングツリー 
|
B <- HEAD,インデックス
|
A 

# git reset HEAD^
# HEADとインデックスがHEAD^に移動する

  <- ワーキングツリー 
|
B 
|
A <- HEAD,インデックス

# git reset --hard HEAD
# HEAD,インデックス,ワーキングツリーがすべてHEADに移動する

B <- HEAD,インデックス,ワーキングツリー 
|
A

# git reset --hard HEAD^
# HEAD,インデックス,ワーキングツリーがすべてHEAD^に移動する

B 
|
A <- HEAD,インデックス,ワーキングツリー 


git reflog

コミットにタグを付ける

ファイルを削除する

ワークツリーの内容をまるっと取り置きする

リポジトリに依存関係を持たす

あるリポジトリをsubmoduleとして追加する

submoduleを持っているrepositoryをcloneする

そもそもGitはどのように差分を管理しているか

blob/tree/commitオブジェクトを関連付けて差分管理している

git addgit commitで何をやっているか

  1. echo hoge > hoge.txt & echo hoge > hoge.txt & git add hoge.txt
  2. git ls-files --stage
    • インデックスされたファイルのblob一覧が表示される
  3. git write-tree
    • blobをまとめたtreeが作られ,そのtreeのハッシュが表示される.
  4. echo "first commit" | git commit-tree <git write-treeのハッシュ>
    • git write-treeで作られたtreeをまとめたcommitをつくる
  5. echo <git commit-treeのハッシュ> > .git/refs/heads/masterまたはgit update-ref
    • masterブランチがgit commit-treeのハッシュを指すようにする
  6. git symbolic-ref HEAD refs/heads/master
    • HEADがmasterブランチを指すようにする.
  7. コミット完了

通常のコミットとマージコミットの違い

      E---F---G dev
     /
A---B---C---D master

git checkout dev & git merge master

      E---F---G---I dev
     /           /
A---B---C---D---H master

git checkout master & git merge dev

      E---F---G---I dev,master <=== fast-forward merge...
     /           /
A---B---C---D---H 

git reset --hard HEAD^

      E---F---G dev
     /
A---B---C---D master

      E---F---G---I dev,master
     /           /
A---B---C---D---H 

git reset --hard ORIG_HEAD

      E---F---G---I dev
     /           /
A---B---C---D---H master