CITools >
目次 †
基本フロー †
主にマージリクエスト(GitHub? の場合はプルリクエスト、以下同様)の利用を前提としています。マージリクエスト自体は Git の機能ではありませんが、非常に普及しているソーシャルコーディングの手法です。
ユーザ情報の設定 †
github.comでメールアドレスをマスクしたい場合には、<username>@users.noreply.github.com を設定します。
gitlab.com ではメールアドレスのマスクはまだできないようです(#43521 )。
ユーザ情報を適切に設定しておきます。
$ git config --global user.name 'Alice'
$ git config --global user.email alice@mail.example.com
$ git config -l
リポジトリへの変更権限がある場合 †
開発ブランチで作業する †
CIパイプライン等を経由させたい場合: マージリクエストを利用します。
開発ブランチ(この例では、dev-br )を作成し、そこにコミットした変更を push します。
$ git checkout -b dev-br
Switched to a new branch 'dev-br'
$ git branch
* dev-br
master
$ vim README.md
...
$ git add README.md
$ git commit -m 'modify README.'
[dev-br 3823e82] modify README.
1 file changed, 1 insertion(+)
$ git push origin dev-br
...
このブランチの変更を(一般的には master ブランチに)マージしてもらうため、WebUIからマージリクエストを出します。この時点でマージリクエストビルド(主にテスト目的)を実行するようにCIツールをセットアップするとよいでしょう。
変更内容に問題がある場合には、再度開発ブランチに修正をコミットし、push します。その変更内容は該当のマージリクエストに反映されます。
マージ権限はあるため、変更内容に問題がなければマージを実行します。この時点でパブリッシュまたデプロイを実行するようにCIツールをセットアップするとよいでしょう。
もうリモート開発ブランチが不要な場合には、それを削除します。WebUIから削除するのが簡単です。
ローカルの開発ブランチは以下の要領で削除します。
$ git checkout master
$ git pull
$ git branch --delete dev-br
Deleted branch dev-br (was 3823e82).
特定の変更コミットを取り消す †
過去の特定の変更コミットを取り消したい場合があります。
取り消したいコミットのSHAハッシュを指定して revert します。コンフリクトがない場合にはそのまま取り消されたコミットが作成されます。
$ git revert <commit sha>
コンフリクトがある場合には以下のようになりますので、コンフリクトを解消した後に revert を続行します。
error: could not revert ...
hint: after resolving the conflicts, mark the corrected paths
hint: with 'git add <paths>' or 'git rm <paths>'
hint: and commit the result with 'git commit'
# コンフリクトを解消し、git add などを実行します
$ git revert --continue
他のリポジトリへのコントリビュート †
フォークして開発ブランチで作業する †
直接の変更権限がないリポジトリへのコントリビュートにも、もちろんマージリクエストを利用します。
まず対象のリポジトリ(この例では git@gitlab.io.example.com :sandbox/hello-world.git とします)を任意のグループにフォークします。フォーク先グループはプライベート(この例では、alice )でも共同開発グループ(GitHub? では、Organization)でも構いません。 共同開発グループの場合、コントリビュートに際してメンバーの助けを受けることが容易になります。
フォークしたリポジトリをクローンします。
$ git clone git@gitlab.io.example.com:alice/hello-world.git
$ cd hello-world/
2回目以降のコントリビュートの際には、ソースをフォーク元と同期させておきます(下記参照)。
この後、開発ブランチを作成し、そこにコミットした変更を push するのは上記と同様です。
$ git checkout -b dev-br
$ vim README.md
...
$ git add README.md
$ git commit -m 'add message.'
[dev-br c41d836] add message.
1 file changed, 2 insertions(+)
$ git push origin dev-br
...
このブランチの変更をフォーク元にマージしてもらうため、WebUIからマージ先がフォーク元のそれ(この例の場合は、sandbox/hello-world:master )になっていることを確認してから、マージリクエストを出します。この時点でマージリクエストビルド(主にテスト目的)を実行するようにCIツールがセットアップされている場合がほとんどです。テストにパスするソースをコントリビュートするよう心がけましょう。
変更内容に問題がある場合には、再度開発ブランチに修正をコミットし、push します。その変更内容は該当のマージリクエストに反映されます。
マージリクエスト上での遣り取りの後、変更内容に問題がないことが確認されればフォーク元の管理者がマージを実行してくれます(場合によっては変更が却下(クローズ)されます)。
もうリモート開発ブランチが不要な場合には、それを削除します。WebUIから削除するのが簡単です。
ローカルの開発ブランチは以下の要領で削除します。この場合、HEADへのマージはありませんので -D オプションで強制削除します。
$ git checkout master
$ git branch -D dev-br
Deleted branch dev-br (was c41d836).
フォーク元との同期 †
フォークしたリポジトリは容易に陳腐化します。次回以降のコントリビュートの際には、事前にフォーク元との同期を行ってから開発作業を開始するようにしましょう。
まずフォーク元のリポジトリを upstream という名前で追加しておきます。
$ git branch
* master
$ git remote add upstream git@gitlab.io.example.com:sandbox/hello-world.git
フォーク元の変更をフェッチしてマージします。
$ git fetch upstream
...
$ git merge upstream/master
Updating e85d2b5..42eefa1
Fast-forward
README.md | 2 ++
1 file changed, 2 insertions(+)
さあ開発ブランチを作成し、開発をはじめましょう。
フォーク元との再同期 †
開発ブランチで作業中にフォーク元(upstream )が更新される場合もよくあります。そのような場合にはフォーク元の更新を開発ブランチに取り込みます。
まず、master ブランチに移動し、フォーク元の更新をその master ブランチにマージします。
$ git checkout master
$ git fetch upstream
$ git merge upstream/master
開発ブランチに戻り、最新の master にリベースします。コンフリクトがない場合にはそのままマージが完了します。
$ git checkout dev-br
$ git rebase master
コンフリクトした場合には、コンフリクトを解消しリベースを続行します。もしリベースを中止する場合には、git rebase --abort を実行します。
# コンフリクトを解消し、git add等を行う
$ git rebase --continue
すでにリモートにその開発ブランチを push している場合には、-f オプションを付けて強制的に push します。
$ git push -f origin dev-br
マージリクエストのコミット履歴をまとめる †
フォーク元のポリシーによっては、(マージ後の履歴をシンプルにするため)一つのマージリクエストに含まれる複数のコミットをまとめるように求められるかもしれません。そのような場合には git rebase を実行します。
まとめたい直近のコミットの数を指定して rebase します。
$ git rebase -i HEAD~4
エディタが開きますので、直前のコミットにまとめたいコミット(すべて)の先頭の pick を squash (もしくは s )に変更して保存の上閉じます。
次にまとめのコミットメッセージを入力するためのエディタが開きますので、メッセージを修正の上保存してこれも閉じます。これで複数のコミットがまとまります。
最後にこの履歴の改変を push します。なお、このような rebase は関係者が合意の上、行うものですのでリモートに強制的に push しても問題ありません。
$ git push -f origin dev-br
Tips †
ブランチの確認 †
$ git branch
* dev-br
master
$ git branch -a
* dev-br
master
remotes/origin/HEAD -> origin/master
remotes/origin/master
remotes/upstream/master
git-prompt †
~/.bashrc : プロンプトへの表示と色付け。以下の要領で設定します。色付けする場合には、$PS1 ではなく、$PROMPT_COMMAND に設定します。
# git-prompt.sh
# $ wget https://raw.githubusercontent.com/git/git/master/contrib/completion/git-prompt.sh -O ~/.git-prompt.sh
# $ chmod a+x ~/.git-prompt.sh
if [ -f ~/ .git-prompt.sh ] ; then
GIT_PS1_SHOWCOLORHINTS =1
GIT_PS1_SHOWDIRTYSTATE =1
GIT_PS1_SHOWUPSTREAM =1
GIT_PS1_SHOWUNTRACKEDFILES =
GIT_PS1_SHOWSTASHSTATE =1
source ~/ .git-prompt.sh
if [ -n "$GIT_PS1_SHOWCOLORHINTS " ] ; then
PROMPT_COMMAND ="__git_ps1 '\[\e]0;\u@\h: \w\a\]\$ {debian_chroot:+(\$ debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]' '\n \$ ' ' (%s)';${PROMPT_COMMAND} "
#PROMPT_COMMAND="${PROMPT_COMMAND%;};__git_ps1 '\[\e]0;\u@\h: \w\a\]\${debian_chroot:+(\$debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]' '\n\$ ' ' (%s)';"
else
PS1 ='\[\e]0;\u@\h: \w\a\]${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]$(__git_ps1)\n\$ '
fi
fi
既存の$PROMPT_COMMAND 設定(_direnv_hook; 等)を上書きしないように注意します。
__git_ps1 関数の引数は、先行文字列、後続文字列、フォーマット(オプションでデフォルトは ' (%s)')です。
またプロンプト中の変数も設定時に展開されないように$ をエスケープする必要があります。
git-credential †
以下の例では、認証情報を常駐プロセスに3600秒間記憶するように設定しています。
git config --global credential.helper 'cache --timeout=3600'