Androidはワンツーパンチ 三歩進んで二歩下がる

プログラミングやどうでもいい話

GIT IMMERSIONで無料でGitを学ぶ メモ4

GIT IMMERSIONで無料でGitを学ぶ メモ1
GIT IMMERSIONで無料でGitを学ぶ メモ2
GIT IMMERSIONで無料でGitを学ぶ メモ3
に引き続きメモその4です。

続きはこちら
GIT IMMERSIONで無料でGitを学ぶ メモ5
GIT IMMERSIONで無料でGitを学ぶ メモ6
GIT IMMERSIONで無料でGitを学ぶ メモ7
GIT IMMERSIONで無料でGitを学ぶ メモ8

GIT IMMERSIONというGitのやり方を教えてくれるチュートリアルサイトを勉強しながらメモを取っています。
自分用なのであまり見やすいものではないです。

※ $ git hist コマンドはGIT IMMERSION LAB11 でコマンドエイリアスを設定しているので
hist = log --pretty=format:'%h %ad | %s%d [%an]' --graph --date=short
の意味です。

GIT IMMERSION LAB28

マージ

2つに枝分かれしたブランチを1つのブランチに戻す方法を学ぶ。

2つのブランチの変更をマージしよう。greetブランチに戻って、greetにmasterをマージしよう​。
$ git checkout greet
$ git merge master
$ git hist --all

実行結果は以下のようなイメージだ。

                                          • -

$ git checkout greet
Switched to branch 'greet'
$ git merge master
Merge made by the 'recursive' strategy.
README | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
create mode 100644 README
$ git hist --all
* a0750b6 2012-03-06 | Merge branch 'master' into greet (HEAD, greet) [Jim Weirich]
|\
| * 3ce0095 2012-03-06 | Added README (master) [Jim Weirich]
* | e2257cb 2012-03-06 | Updated Rakefile [Jim Weirich]
* | a93f079 2012-03-06 | Hello uses Greeter [Jim Weirich]
* | 4b9457a 2012-03-06 | Added greeter class [Jim Weirich]
|/
* 76ba0a7 2012-03-06 | Added a Rakefile. [Jim Weirich]
* b8f15c3 2012-03-06 | Moved hello.rb to lib [Jim Weirich]
* 9c78ad8 2012-03-06 | Add an author/email comment [Jim Weirich]
* 4054321 2012-03-06 | Added a comment (v1) [Jim Weirich]
* 1b754e9 2012-03-06 | Added a default value (v1-beta) [Jim Weirich]
* 3053491 2012-03-06 | Using ARGV [Jim Weirich]
* 3cbf83b 2012-03-06 | First Commit [Jim Weirich]

                                          • -

定期的にgreetブランチにmasterをマージすることで、masterの変更を余すことなく取り入れ、greetへの変更メインラインの変更と互換性を保つことができる。

しかしそのやり方では 汚いコミットグラフが出来てしまう。後で、リベースのオプションを見てみよう。

次回
masterとgreetがそれぞれのブランチで同じ箇所を変更して、競合がおこった場合どうなるだろう?

GIT IMMERSION LAB29

競合を起こしてみようか

masterブランチに競合する変更を入れてみよう。

masterブランチに切り替える。
$ git checkout master

lib/hello.rbを次のように修正する

                                          • -

puts "What's your name"
my_name = gets.strip

puts "Hello, #{my_name}!"

                                          • -

次のように実行してみよう
$ git add lib/hello.rb
$ git commit -m "Made interactive"

ブランチを見てみよう
$ git hist --all
実行結果は以下のようなイメージだ。

                                          • -

$ git hist --all
* a0750b6 2012-03-06 | Merge branch 'master' into greet (greet) [Jim Weirich]
|\
* | e2257cb 2012-03-06 | Updated Rakefile [Jim Weirich]
* | a93f079 2012-03-06 | Hello uses Greeter [Jim Weirich]
* | 4b9457a 2012-03-06 | Added greeter class [Jim Weirich]
| | * 6b6beca 2012-03-06 | Made interactive (HEAD, master) [Jim Weirich]
| |/
| * 3ce0095 2012-03-06 | Added README [Jim Weirich]
|/
* 76ba0a7 2012-03-06 | Added a Rakefile. [Jim Weirich]
* b8f15c3 2012-03-06 | Moved hello.rb to lib [Jim Weirich]
* 9c78ad8 2012-03-06 | Add an author/email comment [Jim Weirich]
* 4054321 2012-03-06 | Added a comment (v1) [Jim Weirich]
* 1b754e9 2012-03-06 | Added a default value (v1-beta) [Jim Weirich]
* 3053491 2012-03-06 | Using ARGV [Jim Weirich]
* 3cbf83b 2012-03-06 | First Commit [Jim Weirich]

                                          • -

“Added README”というmasterのコミットはgreetにマージされている。しかし、今greetにマージされていないコミットがmaster上に出来た。

次回
masterに対する最新の変更はgreetで行なっている変更と衝突している。次はこれらの変更を解決しよう。

GIT IMMERSION LAB30

競合を解決する

マージ中の競合を扱う方法を学ぶ。

greetブランチに戻り新しいmasterブランチとマージを試してみる。
$ git checkout greet
$ git merge master

実行結果は以下のようなイメージだ。

                                          • -

$ git checkout greet
Switched to branch 'greet'
$ git merge master
Auto-merging lib/hello.rb
CONFLICT (content): Merge conflict in lib/hello.rb
Automatic merge failed; fix conflicts and then commit the result.

                                          • -

lib/hello.rbを開いたら次のように見えるはずだ。

                                          • -

<<<<<<< HEAD
require 'greeter'

# Default is World
name = ARGV.first || "World"

greeter = Greeter.new(name)
puts greeter.greet
=======
# Default is World

puts "What's your name"
my_name = gets.strip

puts "Hello, #{my_name}!"
>>>>>>> master

                                          • -

最初の部分は現在のブランチ(greet)のヘッドのバージョンだ。
2番めの部分はmasterブランチのバージョンだ。

競合箇所は手動で修正する必要がある。
ib/hello.rbを次のように修正してみよう。

                                          • -

require 'greeter'

puts "What's your name"
my_name = gets.strip

greeter = Greeter.new(my_name)
puts greeter.greet

                                          • -

この競合修正をコミットする。
次のように実行してみよう
$ git add lib/hello.rb
$ git commit -m "Merged master fixed conflict."

実行結果は以下のようなイメージだ。

                                          • -

$ git add lib/hello.rb
$ git commit -m "Merged master fixed conflict."
[greet 3165f66] Merged master fixed conflict.

                                          • -

進化したマージング
gitはグラフィカルマージツールを提供していませんが、嬉しいことにサードパーティ製のマージツールが用意されている。http://onestepback.org/index.cgi/Tech/Git/UsingP4MergeWithGit.red
「P4Merge」(Perforce Visual Merge and Diff Tools)というグラフィカルツールの説明を見てね。

GIT IMMERSION LAB31

REBASING VS MERGING

rebaseとmergeの違いを学ぶ。

議論
マージ・リベースの違いを探ってみよう。そのために初めてのマージの前にリポジトリを巻き戻してから、同じ手順をやり直す必要がある。今度はmergeではなくrebaseを使用する。

resetコマンドを使ってブランチを過去の時点に戻してみよう。

GIT IMMERSION LAB32

greetブランチをリセットする。

初めてのマージの前のポイントにgreetブランチをリセットする。
masterブランチをgreetブランチに統合する前に戻してみよう。どの時点のコミットでもお望みの時点にリセットすることが出来る。

本質的には、コミットツリー内の任意の場所を指すようにブランチのポインタを変更している。

今回のケースでは、masterとmergeする時点までgreetを戻したいのでmerge前の最後のコミットを特定しよう。

実行してみよう
$ git checkout greet
$ git hist

実行結果は以下のようなイメージだ。

                                          • -

$ git checkout greet
Already on 'greet'
$ git hist
* 3165f66 2012-03-06 | Merged master fixed conflict. (HEAD, greet) [Jim Weirich]
|\
| * 6b6beca 2012-03-06 | Made interactive (master) [Jim Weirich]
* | a0750b6 2012-03-06 | Merge branch 'master' into greet [Jim Weirich]
|\ \
| |/
| * 3ce0095 2012-03-06 | Added README [Jim Weirich]
* | e2257cb 2012-03-06 | Updated Rakefile [Jim Weirich]
* | a93f079 2012-03-06 | Hello uses Greeter [Jim Weirich]
* | 4b9457a 2012-03-06 | Added greeter class [Jim Weirich]
|/
* 76ba0a7 2012-03-06 | Added a Rakefile. [Jim Weirich]
* b8f15c3 2012-03-06 | Moved hello.rb to lib [Jim Weirich]
* 9c78ad8 2012-03-06 | Add an author/email comment [Jim Weirich]
* 4054321 2012-03-06 | Added a comment (v1) [Jim Weirich]
* 1b754e9 2012-03-06 | Added a default value (v1-beta) [Jim Weirich]
* 3053491 2012-03-06 | Using ARGV [Jim Weirich]
* 3cbf83b 2012-03-06 | First Commit [Jim Weirich]

                                          • -

少し読みづらいね。でも“Updated Rakefile”コミットの箇所を見てみれば、greetブランチがマージする直前のコミットだということがわかる。greetブランチをそのコミットまでリセットしてみよう。

実行してみよう
にはさっき表示されたコミットのハッシュを入力してくれ。
$ git reset --hard

実行結果は以下のようなイメージだ。

                                          • -

$ git reset --hard e2257cb
HEAD is now at e2257cb Updated Rakefile

                                          • -

ログをチェックすると、履歴からマージのコミットが消えている。
$ git hist --all

実行結果は以下のようなイメージだ。

                                          • -

$ git hist --all
* e2257cb 2012-03-06 | Updated Rakefile (HEAD, greet) [Jim Weirich]
* a93f079 2012-03-06 | Hello uses Greeter [Jim Weirich]
* 4b9457a 2012-03-06 | Added greeter class [Jim Weirich]
| * 6b6beca 2012-03-06 | Made interactive (master) [Jim Weirich]
| * 3ce0095 2012-03-06 | Added README [Jim Weirich]
|/
* 76ba0a7 2012-03-06 | Added a Rakefile. [Jim Weirich]
* b8f15c3 2012-03-06 | Moved hello.rb to lib [Jim Weirich]
* 9c78ad8 2012-03-06 | Add an author/email comment [Jim Weirich]
* 4054321 2012-03-06 | Added a comment (v1) [Jim Weirich]
* 1b754e9 2012-03-06 | Added a default value (v1-beta) [Jim Weirich]
* 3053491 2012-03-06 | Using ARGV [Jim Weirich]
* 3cbf83b 2012-03-06 | First Commit [Jim Weirich]

                                          • -