Help us understand the problem. What is going on with this article?

Gitでローカルブランチでの作業フローまとめ

More than 1 year has passed since last update.

はじめに

「Gitの使い方わかったけど、やっぱり mergerebase 怖すぎるでしょ」
という方向けに、
「ローカルブランチで mergerebase したら良いんだよ。普段から使えば怖くない」
「いいからバンバン、まとめてけ、まとめてけぇ!」
という提案めいた、筆者自身の作業フローのまとめです。

大まかな手順

  1. とりあえずmasterからブランチを切る
  2. なんか書く(テストでも実装でもドキュメントでも)
  3. 昔のRPGのノリで Commit
  4. 2. と 3. を繰り返し
  5. ここで rebase ですよ(自分のコミットをある程度まとめる)
  6. そして merge ですよ( 事前に pull を行ったmasterを merge
  7. 決めろ! push origin

とりあえずmasterからブランチを切る

暗黙の了承ではありますが、とりあえず自分のこれからやる作業1個につき一つブランチを切りましょう。

なんか書く(テストでも実装でもドキュメントでも)

ノリノリで実装していきましょう。
実装が思いついていない場合はテストでも書きましょう。
テスト要件もはっきりしていない個人案件の場合は、とりあえずドキュメントでもMarkdownやAsciidoc、reStructuredTextなどで作りましょう。

昔のRPGのノリで Commit

昔のバイオハザードシリーズの様にセーブ回数が限られているということは無いですし、
コミットは上書き保存されることも無いです。

ですので、
「1行苦労して書き終えたぜ」
と思ったらそこで即座に git add and git commit しましょう。

でも、動作するか分からないコード書いちゃったよ?

ご安心を。後で rebase するから良いんだよ。

しかし後で、
「どれがいらないコミットだっけ……」
とならないように、プレフィックスをつけておくと幸せになれます。

[Add][alpha] APIのモデルの仮実装

頭に思いついたコードを書いただけなので、動く自信はあまりない。

や、

[beta] APIのモデルをモジュール単体で動作確認した

おおむね良好。ただしテストを考えていないので整合性が取れるかは自信ない。

という感じで。

2. と 3. を繰り返し

以上の、「なんか書く(テストでも実装でもドキュメントでも)」、「昔のRPGのノリで Commit」の手順を、とりあえず1タスク終わるまでやります。

ここで rebase ですよ(自分のコミットをある程度まとめる)

ここまでであなたのブランチには相当のコミットがあると思います。これらをまとめていきます。

初心者殺しの rebase 機能で。

rebase は本当に、
「用法用量を守って正しくお使いください」
サブコマンドですが、 -i オプションを付けて行うと、とても友好的なコマンドになります(個人的な感想です)。

log で自分のコミットを確認

まずはこれです。自分のブランチで一番初めに行ったコミットを確認しておきましょう。

git log でログを出力して、
「どれが今回の変更を始めたコミットだっけー」
と、 最新コミットから何個目か を覚えておきましょう。

覚えたら q を入力してログ表示を終了します。

rebase -i HEAD~ を。

最新コミットから何個目か は覚えてますね?
といっても、忘れたらまた git log で数え直せば良いんですよ。

ここで忘れちゃいけないコマンドが -i オプションです。

今回は「自分の作業だけで17コミットあった」と仮定します。
そんな場合は git rebase -i HEAD~18 を実行します。
一つ多く指定するのがコツ。

さて、いつもコミットメッセージを編集するときに使うエディタが起動すると思います。

そのメッセージの下の方にこんな説明が書いていると思います。

# Commands:
# p, pick = use commit
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
# f, fixup = like "squash", but discard this commit's log message
# x, exec = run command (the rest of the line) using shell
# d, drop <commit> = remove commit
# l, label <label> = label current HEAD with a name
# t, reset <label> = reset HEAD to a label
# m, merge [-C <commit> | -c <commit>] <label> [# <oneline>]
# .       create a merge commit using the original merge commit's
# .       message (or the oneline, if no original merge commit was
# .       specified). Use -c <commit> to reword the commit message.

とりあえず今回覚えておけば良いと思うのは、

  • p, pick
  • r, reword
  • s, squash
  • d, drop

でしょうか。

こんな感じでコミットログが並んでいれば:

pick 443857b [Add][alpha] APIのモデルの仮実装
pick 2482b74 [Mod][beta] APIのモデルの仮実装。テストはまだ
pick 33df862 [Add][alpha] テストの仮実装
pick 4b6725f [Mod][beta]テスト大体できた
pick 68f7b34 [Mod]テストコードの実行結果を踏まえて変更

こういう風に書き直すといいかもしれません:

drop 443857b [Add][alpha] APIのモデルの仮実装
drop 2482b74 [Mod][beta] APIのモデルの仮実装。テストはまだ
reword 33df862 [Add][alpha] テストの仮実装
squash 4b6725f [Mod][beta]テスト大体できた
pick 68f7b34 [Mod]テストコードの実行結果を踏まえて変更

最初の2つ、443857b, 2482b74drop したのは、
「テストコードもなく、思いついた限りでの実装を先にしてしまったので、動作はおろかビルドできるかも保証できるものではない」
為です。

その次の 33df862 のコミットは、仮ではあるものの、
「要求する動作をテストコードを書いてはっきりさせた」
コミットなので、次のコミット 4b6725f の変更とまとめて、コミットメッセージを編集して記録することにします。

さらに、 68f7b34 のコミットは、
「テストコードの実行結果を踏まえて変更(改修)」
したものなので、しっかり記録しておきます。

ここで、 rebase 計画(と勝手に言ってみる)を保存してエディタを終了すると、あとはgitがよろしくやってくれます。

Conflictが発生したときは……ちゃんと解決して git rebase --continue しましょう。
「やっぱりなんかおかしい」
と思ったら、 git rebase --abortrebase 操作を無かったことにできます。

そして merge ですよ( 事前に pull を行ったmasterブランチを merge

masterブランチは毎朝 origin master ブランチを pull しているものと仮定します。
そうであったとしても、この工程を行う前には念の為他の人の最新の変更を取り込める様に、masterブランチで pull することをおすすめします。

では、作業ブランチで git merge master を決めちゃってください。
merge という言葉の響きだと、
「masterブランチそのものが消えるのでは?」
と思われるかもしれませんが、それはないです。あくまでmasterブランチはそのままに、masterブランチの変更を作業ブランチに取り込むだけです。

これで安心して push してプルリクエストを発行できますね!

ゑ、Conflictした……しかも他人のコミットと……。

編集者同士で要相談。

決めろ! push origin

さあ、これでプルリクエストまであともう少しです。後は、

git push origin {作業ブランチ名}

しちゃってください!

こういう時どうするの?

この項は後で内容を充実させますねー。

別のブランチで作業しちゃった……(コミットはしていない)

変更を一時的に退避!キメろgit stash - Qiita

その変更が一度もステージングしていないファイルであれば、そのまま git checkout で適切なブランチに移動して、そのまま作業しましょう。

ステージングしてるやつだったり、変更がGitに認識されている場合は、まず git stash save コマンドで保管。
その後、適切なブランチに git checkout しましょう。
そうしたら、 git stash pop を実行です。

そうすると素晴らしいことに、自分のさっきまで変更していた内容が、移動先のブランチに反映されます。

別のブランチで作業しちゃった……(コミットもした)

とりあえずいいとこ取り。 cherry-pick

コミットしたなら、まずは git log で コミットハッシュをコピペしておきます。最初の7桁くらいで大丈夫だった記憶。

そして、適切なブランチに git checkout で移動します。

ここでGitのいいとこ取り機能、 cherry-pick を使います。 `git cherry-pick {コピペしたコミットハッシュ}

あとはコンフリクトしていなければ、熟したさくらんぼをつまんで取ったように変更が反映されます。もちろんコミットログも。

ついでにお片付けで、間違えたブランチで git reset --hard HEAD^ として、変更を一つ前に戻せば完璧ですね!

ついうっかり、同じブランチで別の目的の変更をしてしまってな……

Gitでやらかした時に使える19個の奥義 - やらかし7:大きすぎるコミットをスマートに分割したい時 - Qiita

勢いに乗ってると、やりますね。

実はGitは「ファイル単位」ではなく「ファイルの中の各場所の変更単位」でコミットできます。hunkと書きます。

筆者はこの機能を使ったことがなく、今まで git stash と変更内容を別ファイルに待避という方法でやっちゃっていましたが、対話モードが起動するんですね。

git add コマンドの使い方と、主要オプション | WWWクリエイターズ

とりあえず覚えておけばいいと思うのは、

  • y: hunkをコミットする
  • n: hunkを捨てる
  • ?: コマンド一覧を表示

でしょうか。

rebaseするコミット間違えちゃったままrebase完了しちゃった。テヘペロ

あー、君もやっちゃったかぁ。大丈夫、筆者もよくやる。

そんなときは「Git自体の操作の履歴」を確認し、「その操作までリセット」しましょう。

ということで、とりあえず 一応やり直せるが慎重に git reflog コマンドで操作の履歴を確認。
そして、 `git reset HEAD@{{ここにreflogで確認したHEAD番号を入れる}}` を実行しましょう。

ふぅ、ヒヤッとしたぜ。

まとめ

という感じで僕はローカルブランチで作業しています。
皆様のGitによる精神的安定のできるプログラミングライフの参考になれば幸いです。

Gitは変更履歴を重んじるプログラマや物書きの頼れる仲間だよ!

参考資料

P.S.

「もっと簡略化できるだろ」
というご提案は、例を交えてコメントを頂けると幸いです。

「このコマンド分からない……」
調べていただけると幸いです。この記事はあくまでgitへの恐怖心を、理屈や理論の説明は省いて使ってもらって拭うことと、筆者が自分の作業フローのまとめる為に書いたものです。

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away