Git
Gitとは
- 分散型バージョン管理システム
- 開発者はリーナス・トーバルズ(Linuxカーネル開発者)
Gitの特徴
- ユーザーのワーキングディレクトリに全履歴を含んだリポジトリの完全な複製が作られる
- ネットワークにアクセスできないなどの理由で中心リポジトリにアクセスできない環境でも、履歴の調査や変更の記録といったほとんどの作業を行うことができる
- 設計はBitKeeperとMonotoneが元
Gitの概念
Git運用フロー
Git
リリースノート
Gitコマンド
設定
Terminal
# メールアドレスの設定
git config --global user.email "登録メールアドレス"
# メッセージの色分け
git config --global color.ui true
# 設定値の一覧
git config -l
# ヘルプ参照
git config --help
# ヘルプ参照
git help
コミットユーザーを指定、パスワードを省略する場合
.git/config
...途中省略...
[remote "origin"]
url = https://webmaster-patche:%password%@github.com/webmaster-patche/capistrano_sample_app_v1.git
fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
remote = origin
merge = refs/heads/master
リポジトリ操作
リポジトリの複製
git clone %url%
リポジトリの操作
# リモートリポジトリへの接続一覧を表示
git remote
# リモートリポジトリへステージング
git remote add origin/%remoteRepositoryName% git@%address%
# リモートリポジトリ削除(ローカルリポジトリ同名)
git remote rm origin
ブランチ操作
ブランチ確認
# ローカルの一覧表示
git branch
# ローカル&リモートの一覧表示
git branch -a
# リモートの一覧表示
git branch -r
ブランチの操作
# 指定のブランチのファイルを確認(view)
git show %branche%:%filePath%
# リモートブランチからローカルブランチへの同期
git fetch origin
# 指定のファイルをリモートブランチから取得・上書き
git checkout %branche% -- %filePath%
# ディレクトリ毎上書き
git checkout %branche% -- %directoryPath%
# リモートブランチからローカルブランチ同期
git pull origin %brancheName%
# ローカルブランチからリモートブランチに同期
git push origin %brancheName%
# ローカルブランチから強制的にリモートブランチに同期(上書き)
git push -f origin %brancheName%
# 現在のブランチから指定ブランチにリベース
git rebase -i %brancheName%
# リベース中断
git rebase -abort
# リベース再開
git rebase -continue
# 指定のブランチ(n個前のコミット)に対してリベース
git rebase -i HEAD~%n%
リベースについて
# masterブランチを最新の状態にし、リベースしたいブランチをチェックアウトする
git checkout master
git fetch origin
git pull origin master
git checkout hoge
# 作業ブランチにmasterブランチをリベース
git pull --rebase origin master # masterの最新コミットからブランチを派生させる
# コンフリクトの解消(ここから)
Failed to merge in the changes.
# コンフリクト解消したファイルのステージング
git add .
# リベースの再開(ここまで)
git rebase --continue
# 以降、ここからここまでを繰り返す
# 尚、リベースしたいブランチ側の変更を破棄する場合
git push origin %brancheName% -f
- 一時的な変更だった場合
Terminal
git checkout rebase_from
M README.md
Switched to branch 'rebase_from'
Your branch is up to date with 'origin/rebase_from'.
git pull
remote: Enumerating objects: 102, done.
remote: Counting objects: 100% (102/102), done.
remote: Compressing objects: 100% (17/17), done.
remote: Total 89 (delta 73), reused 88 (delta 72), pack-reused 0
Unpacking objects: 100% (89/89), done.
From https://github.com/webmaster-patche/sample
+ c435d3787...1c7f4857 rebase_from -> origin/rebase_from (forced update)
Already up to date.
git checkout feature/rebase_to
M README.md
Switched to branch 'feature/rebase_to'
Your branch is up to date with 'origin/feature/rebase_to'.
git rebase rebase_from
error: cannot rebase: You have unstaged changes.
error: Please commit or stash them.
$ git status
On branch feature/rebase_to
Your branch is up to date with 'origin/feature/rebase_to'.
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: README.md
no changes added to commit (use "git add" and/or "git commit -a")
git checkout README.md
Updated 1 path from the index
git rebase rebase_from
First, rewinding head to replay your work on top of it...
Applying: [#999] [schema] ユーザー
git status
On branch feature/rebase_to
Your branch and 'origin/feature/rebase_to' have diverged,
and have 2 and 1 different commits each, respectively.
(use "git pull" to merge the remote branch into yours)
nothing to commit, working tree clean
ブランチの作成
# 作成のみ
git branch %branchName%
# カレントブランチ切り替えを同時に行う
git branch -b %branchName%
ブランチの削除
# ブランチの削除
git branch -d %ブランチ名%
ブランチの比較
# ブランチAとブランチBのファイル比較
git diff %brancheA%:%filePath% %brancheB%:%filePath%
# ファイルパスが同じものを比較する場合は以下の方が便利かつ安全
git diff %brancheA% %brancheB% %filePath%
# コミットの差分比較
git diff --cached
ブランチの追跡
Terminal
git pull
There is no tracking information for the current branch.
Please specify which branch you want to merge with.
See git-pull(1) for details.
git pull <remote> <branch>
If you wish to set tracking information for this branch you can do so with:
git branch --set-upstream-to=origin/<branch> feature/hogehoge
この様なエラーメッセージが表示された場合は、 set-upstream
でブランチを追跡する
Terminal
git branch --set-upstream-to=origin/feature/hogehoge
ブランチ退避
ワーキングディレクトリのスタック領域退避
# スタッシュの保存
git stash save
# スタッシュ一覧
git stash list
# スタッシュ一覧(変更内容をgit log形式で確認)
git stash list -p
# スタッシュの変更確認
git stash show %stashName%
スタック領域からワーキングディレクトリに反映
# ワーキングディレクトリに戻すだけ
git stash apply %stashName%
# ステージング状態を保持して反映
git stash apply %stashName% --index
# スタック領域
# ワーキングディレクトリに戻し、スタック領域から削除
git stash pop %stashName%
# スタッシュ削除
git stash drop %stashName%
ブランチの併合
# feature/xxxxのマージ
git merge feature/xxxx
# CONFLICT
Auto-merging lib/hogehoge.js
CONFLICT (content): Merge conflict in lib/hogehoge.js
Automatic merge failed; fix conflicts and then commit the result.
## 状態の確認
git status
On branch feature/develop_2020xxxx
You have unmerged paths.
(fix conflicts and run "git commit")
(use "git merge --abort" to abort the merge)
Unmerged paths:
(use "git add <file>..." to mark resolution)
both modified: lib/hogehoge.js
no changes added to commit (use "git add" and/or "git commit -a")
## 衝突の解消
vi lib/hogehoge.js
<<<<<<< HEAD
This sentence is added by master branch.
=======
This sentence is added by feature branch.
>>>>>>> feature/xxxx
## 解消のマーク
git add lib/hogehoge.js
## コミット
git commit
コミット操作
コミットの打ち消し
# rebaseを無かったことにする
git reset --hard ORIG_HEAD
# ORIG_HEAD リモートブランチのHEAD?
# 直前のコミットをなかった事にする
git reset --hard HEAD^
# --hard コミット取り消した上でワークディレクトリの内容も書き換えたい
# --soft ワークディレクトリの内容はそのままでコミットだけを取り消したい
# HEAD^ 直前のコミット
# HEAD~{%n%} n個前のコミット
# @^ HEAD^と同じ
# @~%n% HEAD~{%n%}と同じ
# HEAD^^^ HEAD~{3}と同じ
# HEAD~~~ HEAD^^^とHEAD~{3}と@^^^は同じ
- --softの場合、直前のコミットのみを取り消し、ワーキングコピーはadd indexした状態に戻す
log
$ git status
On branch %branch_name%
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
modified: app/**/*****.rb
modified: app/**/*****.rb
modified: app/**/*****.rb
new file: db/migrate/****.rb
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: ****
modified: app/**/*****.rb
modified: app/**/*****.rb
modified: app/**/*****.rb
Untracked files:
(use "git add <file>..." to include in what will be committed)
hogehoge.txt
コミットの打ち消し(履歴を残す)
正確には指定のコミットを修正するので、元々のコミットを無かったことにした上で、新しいコミットとする
-
取り消したいコミットを打ち消すようなコミットを新しく作成する処理
# 元々のコミットの取り消し
git revert %コミットのハッシュ値%
# ※editorが起動する(quitすると指定のコミットが無かったことになる(打ち消し用の)コミットがされる)
# 指定のコミット分、全てワーキングディレクトリに戻る
# ***作業***
# インデックス、コミット
# pushする
# 打ち消し用のコミットとは別に、元々のコミットを変更したコミットができる
# 元々のコミットの取り消しをしたコミットを取り消す
# 要はrevertをrevertする
git revert %コミットのハッシュ値%
# 〜上記繰り返し〜
git revert %revertコミットのハッシュ値%
# 〜上記繰り返し〜
コミットの上書き
# 直前コミットの修正
git commit --amend
# ※editorが起動する(quitするとコミットされる)
# エディタなしでコミットの修正
git commit --amend --no-edit
# ※git add .の後などに使うと便利
コミットメッセージを修正したり、コミットし忘れたファイルをインデックス追加してコミットするのをまとめたりする
一度pushしたり、rebaseした場合はamendするとpush出来ないため、強制オプションが必要になるので注意
Terminal
git push origin %branch_name% -f
-fをつける事でpushできます
コミットの操作
# コミットを直接ローカルに上書き
git cherry-pick %commitID%
commitIDはgit logで確認できる
ワーキングディレクトリ操作
ワーキングディレクトリにGit適用
git init
ワーキングディレクトリの状態
# 差分、状態の確認
git status
ログ
- 自分がコミットした物を日付をy/m/d形式で出力する
Terminal
git log --date=short --pretty=format:"%h - %ae, %ad : %s" | grep "%name%"
トラブルシューティング
git push
- You have not concluded your merge"というエラーが発生する
- gitでpullかpushすると"You have not concluded your merge"というエラーが発生する
- これはコンフリクトが起こっているために、マージが上手くできず完了していない状態
# 直前のマージコミットを取り消し
git reset --merge
# merge + fetch
git pull origin %remoteBranche%
# するとvim(またはデフォルトで指定しているテキストエディタ)が立ち上がる
# コミットメッセージを編集
# コミット
git commit -m "競合解決"
# リモートブランチにpush
git push
- Git, fatal: The remote end hung up unexpectedly
git config http.postBuffer 524288000
ノウハウ
ブランチ運用のKPI
-
1コミットはストーリー・施策・機能単位で行う
コミットを作業単位で作成すれば、コミットログが積み重なってしまう為、例えば、Githubの様にスカッシュマージを運用するならともかく、スカッシュマージをしないのであれば、インデックスの追加を行うのが好ましい
orphanブランチ
orphanブランチとは
親のいないと言う意味の orphanブランチを作成し、そこに切り替えた後、このブランチ上に対して作られるコミットは、親コミットがなく、その他のすべてのブランチおよびコミットから切り離された、新しいヒストリーを持つこととなる
log
$ git checkout --orphan %orphan branch name%
# この状態で、いつものように Git 管理下におきたいファイルをステージングして commit する。何も commit していない状態だと git branch を実行しても tmp ブランチは表示されないようだ。
$ git add .
$ git commit -m "first commmit"
# この時点で master と履歴が 1 つの tmp というブランチが存在することになる。あとは master ブランチを tmp ブランチで push して履歴をすべて削除した master ブランチに改変する。
$ push -f . %orphan branch name%:master
# 別のリモートリポジトリに push
# GitHub から clone したリポジトリを履歴を削除した上で BitBucket で新たに管理を開始したい場合などは、まず上記の手順で履歴を削除したリポジトリを作成した後、以下のように origin の url を変更する。
$ git checkout master # カレントブランチを master ブランチに戻す
$ git remote set_url origin git@github.com:username/repository.git
# あとはリモートリポジトリに対して push すればよい。
$ git push origin master
# 最初に作成した orphan なリポジトリはもはや不要なので削除してよい。
$ git branch -d %orphan branch name%
Bitbucket
- コンフリクト解消はrevertが楽
- bitbucketでのプルリクエストの競合について
- masterチェックアウトしてfeatureブランチを作成
- プルリク中のブランチにマージ
- 上記の手順よりrevertした方が楽
最後に
- Gitのバージョンアップデートや拡張機能で変化が激しい為、このまとめは随時編集されます