2018年以降の記事はGitHub Pagesに移行しました

Pro Gitと入門Gitと入門gitと実用GitでGitの復習 無名ブランチ(detached HEAD)からの復活編

参考

無名ブランチ(detached HEAD)とは

要約すると「過去のコミットの状態を眺めるための"便利機能"なのでここに永続的な変更をするなんてとんでもない!」という事らしい。

無名ブランチ状態で作業するとどうなるか

ちょっと「ブランチにいると思いこんだまま無名ブランチで作業し、さーてmasterブランチに戻ってmergeするかぁ……はぁ!?」な状況を作り出してみる。

まずは無名ブランチの準備としてnobraブランチを作る。(これ以降の作業は、本当はnobraブランチでやっていきたいと思っている)

$ git checkout -b nobra
Switched to a new branch 'nobra'

$ touch nobra
$ git add nobra
$ git commit -m "Add nobra"
[nobra d62e4cb] Add nobra
 0 files changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 nobra

$ git g
* d62e4cb  (HEAD, nobra, master) Add nobra
* 7ab5db8  (topic) Add message line 3
* cf6c3d6  Add message line 2
* 38f8aff  Add message line 1
* 93b8e52  Add message line 4
* 0b91a9f  Add message line 5
* 15f636f  Add line number
* fa9eabc  first commit

$ git br
  master d62e4cb Add nobra
* nobra  d62e4cb Add nobra
  topic  7ab5db8 Add message line 3

次に、このnobraブランチのSHA1を指定してcheckoutする。

$ git ch d62e4cb
Note: checking out 'd62e4cb'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:

  git checkout -b new_branch_name

HEAD is now at d62e4cb... Add nobra

detached HEAD状態だよと教えてくれているようだ。このリビジョンのファイル一覧? を見渡したり、実験的な変更やコミットができる。チェックアウトすれば他のブランチに影響を与えすにこの状態を作れる。変更を保持するために新しいブランチを作りたいなら、checkoutコマンドに-bつけて実行すればいいよ……って感じなのかな。ブランチはno branchと表示される。

$ git br
* (no branch) d62e4cb Add nobra
  master      d62e4cb Add nobra
  nobra       d62e4cb Add nobra
  topic       7ab5db8 Add message line 3

この無名ブランチに対し変更をコミット。

$ echo "no branch" >> nobra
$ git add nobra
$ git com "Add message nobra"
[detached HEAD e45c786] Add message nobra
 1 files changed, 1 insertions(+), 0 deletions(-)
 
$ echo "detached HEAD" >> nobra
$ git add nobra
$ git com "Add message nobra"
[detached HEAD 3aec83c] Add message nobra
 1 files changed, 1 insertions(+), 0 deletions(-)

グラフで見るとe45c786, 3aec83cがもくもくと作られている。

$ git g
* 3aec83c  (HEAD) Add message nobra
* e45c786  Add message nobra
* d62e4cb  (nobra, master) Add nobra
* 7ab5db8  (topic) Add message line 3
* cf6c3d6  Add message line 2
* 38f8aff  Add message line 1
* 93b8e52  Add message line 4
* 0b91a9f  Add message line 5
* 15f636f  Add line number
* fa9eabc  first commit

さーて、masterにもどって変更をmergeするかー。*1

$ git checkout master
Previous HEAD position was 3aec83c... Add message nobra
Switched to branch 'master'

グラフを確認するとd62e4cb(masterブランチ)が先頭になっている……だと……。

$ git g
* d62e4cb  (HEAD, nobra, master) Add nobra
* 7ab5db8  (topic) Add message line 3
* cf6c3d6  Add message line 2
* 38f8aff  Add message line 1
* 93b8e52  Add message line 4
* 0b91a9f  Add message line 5
* 15f636f  Add line number
* fa9eabc  first commit

さっきの変更どこいったんだ! 

無名ブランチの救出

コンソールを上へ上へ辿って行けばもしかしたら作業ログが残っていて、そこから無名ブランチになってしまったコミットを特定できるかもしれないけど、ここではgit reflogを使って救済してみる。

$ git reflog
...
d62e4cb HEAD@{6}: checkout: moving from 3aec83cdbfea0b1e96cf3c48937ab84eae1f4ec0 to nobra
3aec83c HEAD@{7}: commit: Add message nobra
e45c786 HEAD@{8}: commit: Add message nobra
...

見えなくなってしまったコミットは(今は)HEAD@{7}にあった!(checkoutしたりcommitすれば1ずつログがずれるから) という事で、この変更が必要だった場合は、ここからトピックブランチでも作成して救出してやればよい。

$ git g
* d62e4cb  (HEAD, nobra, master) Add nobra
* 7ab5db8  (topic) Add message line 3
* cf6c3d6  Add message line 2
* 38f8aff  Add message line 1
* 93b8e52  Add message line 4
* 0b91a9f  Add message line 5
* 15f636f  Add line number
* fa9eabc  first commit

reflogで消えたコミットを確認する。

$ git reflog
...
d62e4cb HEAD@{8}: checkout: moving from 3aec83cdbfea0b1e96cf3c48937ab84eae1f4ec0 to nobra
3aec83c HEAD@{9}: commit: Add message nobra
e45c786 HEAD@{10}: commit: Add message nobra
d62e4cb HEAD@{11}: checkout: moving from nobra to d62e4cb

今はHEAD@{9}になっている。nobraブランチをうつしちゃおう。(新しいブランチを作成してもよい)

$ git branch --f nobra HEAD@{9}

$ git g
* 3aec83c  (nobra) Add message nobra
* e45c786  Add message nobra
* d62e4cb  (HEAD, master) Add nobra
* 7ab5db8  (topic) Add message line 3
* cf6c3d6  Add message line 2
* 38f8aff  Add message line 1
* 93b8e52  Add message line 4
* 0b91a9f  Add message line 5
* 15f636f  Add line number
* fa9eabc  first commit

3aec..が見えるようになった! で、merge。

$ git merge nobra
Updating d62e4cb..3aec83c
Fast-forward
 nobra |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

$ git g
* 3aec83c  (HEAD, nobra, master) Add message nobra
* e45c786  Add message nobra
* d62e4cb  Add nobra
* 7ab5db8  (topic) Add message line 3
* cf6c3d6  Add message line 2
* 38f8aff  Add message line 1
* 93b8e52  Add message line 4
* 0b91a9f  Add message line 5
* 15f636f  Add line number
* fa9eabc  first commit

救出完了!

*1:このPrevious HEAD position was ...というメッセージは無名ブランチからチェックアウトしないと表示されないようだ

Pro Gitと入門Gitと入門gitと実用GitとGit道場#1でGitの復習 rebase編

参考

rebaseとは

入門git P126
土台の置き換え(リベース)にはgit rebaseコマンドを使う。

実用Git P176
一連のコミットのもととなるもの(基点)を変更する際に使います。

Git道場 講義
コミットをかぶせる事*1

コミットの基を変更すると。

パターン1 一般的な?場合(前方移植(forward-port))

Git道場で繰り返したパターンに近いかな。こういうブランチを作る。

       1---2---3(topic)
      /
A---B---C---D(master)

まずは1-5行目にそれぞれ1-5と入力したファイルを用意。

$ touch num
$ git add num
$ git commit -am"first commit"
[master (root-commit) fa9eabc] first commit
 0 files changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 num

$ vi num
$ cat num
$ git commit -am "Add line number"
[master 15f636f] Add line number
 1 files changed, 5 insertions(+), 0 deletions(-)

$ git g
* 15f636f  (HEAD, master) Add line number
* fa9eabc  first commit

次にtopicブランチを作成しを育てる。

$ vi num
$ cat num
1 git add
2
3
4
5
$ git commit -am "Add message line 1"
[topic 29d901e] Add message line 1
 1 files changed, 1 insertions(+), 1 deletions(-)

$ vi num
$ cat num
1 git add
2 git commit
3
4
5
$ git commit -am "Add message line 2"
[topic 0b89cc2] Add message line 2
 1 files changed, 1 insertions(+), 1 deletions(-)

$ vi num
$ cat num
1 git add
2 git commit
3 git rebase
4
5
$ git commit -am "Add message line 3"
[topic 2588a24] Add message line 3
 1 files changed, 1 insertions(+), 1 deletions(-)


$ git g
* 2588a24  (HEAD, topic) Add message line 3
* 0b89cc2  Add message line 2
* 29d901e  Add message line 1
* 15f636f  (master) Add line number
* fa9eabc  first commit

masterに戻り、同じくファイルを編集。

$ git chm
Switched to branch 'master'

$ vi num
$ cat num
1
2
3
4
5 git add from_master
$ git commit -am "Add message line 5"
[master 0b91a9f] Add message line 5
 1 files changed, 1 insertions(+), 1 deletions(-)

$ vi num
$ cat num
1
2
3
4 git commit from_master
5 git add from_master
$ git commit -am "Add message line 4"
[master 93b8e52] Add message line 4
 1 files changed, 1 insertions(+), 1 deletions(-)

$ git g
D  * 93b8e52  (HEAD, master) Add message line 4
C  * 0b91a9f  Add message line 5
 3 | * 2588a24  (topic) Add message line 3
 2 | * 0b89cc2  Add message line 2
 1 | * 29d901e  Add message line 1
   |/
B  * 15f636f  Add line number
A  * fa9eabc  first commit

各コミットをABCD123とすると、こう。

       1---2---3(topic)
      /
A---B---C---D(master)

そして、topicブランチの変更をmasterブランチへ"かぶせる"

$ git ch topic
Switched to branch 'topic'

$ git rebase master
First, rewinding head to replay your work on top of it...
Applying: Add message line 1
Using index info to reconstruct a base tree...
<stdin>:11: trailing whitespace.
1 git add
warning: 1 line adds whitespace errors.
Falling back to patching base and 3-way merge...
Auto-merging num
Applying: Add message line 2
Using index info to reconstruct a base tree...
<stdin>:12: trailing whitespace.
2 git commit
warning: 1 line adds whitespace errors.
Falling back to patching base and 3-way merge...
Auto-merging num
Applying: Add message line 3
Using index info to reconstruct a base tree...
<stdin>:13: trailing whitespace.
3 git rebase
warning: 1 line adds whitespace errors.
Falling back to patching base and 3-way merge...
Auto-merging num
CONFLICT (content): Merge conflict in num
Failed to merge in the changes.
Patch failed at 0003 Add message line 3

When you have resolved this problem run "git rebase --continue".
If you would prefer to skip this patch, instead run "git rebase --skip".
To restore the original branch and stop rebasing run "git rebase --abort".

途中でコンフリクトしたけど、内部ではこうなっている。HEADは今ここ。

  • topicブランチの一つ目の変更をmasterブランチに適用
       1---2---3(topic)
      /
A---B---C---D(master)---1'(HEAD)
  • topicブランチの二つ目の変更をmasterブランチに適用
       1---2---3(topic)
      /
A---B---C---D(master)---1'---2'(HEAD)
  • topicブランチの三つ目の変更をmasterブランチに適用しようとしてコンフリクト
       1---2---3(topic)
      /
A---B---C---D(master)---1'---2'---3'(HEAD)

コンフリクト発生時、グラフはこうなっている。

$ git g
* cf6c3d6  (HEAD) Add message line 2
* 38f8aff  Add message line 1
* 93b8e52  (master) Add message line 4
* 0b91a9f  Add message line 5
| * 2588a24  (topic) Add message line 3
| * 0b89cc2  Add message line 2
| * 29d901e  Add message line 1
|/
* 15f636f  Add line number
* fa9eabc  first commit

Add message line 1と2がmasterブランチから生えてる、イコールmasterブランチにtopicブランチの変更(二つ)がコミットされている。一個ずつ変更を適用してコミットとしているので、もとのtopicブランチとSHA1値が変わっている。

最後の変更をコミットしようとしたらコンフリクトしたので、直す。

$ vi num
$ git add num
$ git rebase --continue
Applying: Add message line 3

rebaseが無事終了。グラフを見てみると…。

$ git g
* 7ab5db8  (HEAD, topic) Add message line 3
* cf6c3d6  Add message line 2
* 38f8aff  Add message line 1
* 93b8e52  (master) Add message line 4
* 0b91a9f  Add message line 5
* 15f636f  Add line number
* fa9eabc  first commit

masterブランチとtopicブランチが一直線になった。旧topicブランチは変更が適用されたという事で削除されている。最終的にはこうなる。

A---B---C---D(master)---1'---2'---3'(HEAD, topic)

一連の流れのreflogはこんな感じ。

7ab5db8 HEAD@{0}: rebase: Add message line 3           # 一つずつ変更を適用
cf6c3d6 HEAD@{1}: rebase: Add message line 2           # 一つずつ変更を適用
38f8aff HEAD@{2}: rebase: Add message line 1           # 一つずつ変更を適用
93b8e52 HEAD@{3}: checkout: moving from topic to 93b8e52... # rebaseが勝手に無名ブランチ(masterの所)へcheckout
2588a24 HEAD@{4}: checkout: moving from master to topic     # rebaseのため自力でcheckoutした
パターン2 rebaseしたいブランチに依存しているブランチがある場合

これを見てまたrebase怖いと思ってしまった。内容を見てみる。

           x---y(subdev)
          /
   1---2---3(dev)
  /
A---B---C(master)

こういうブランチがあった時に、devをrebaseするとどうなるかという事。なるかどうかは別にして、git rebase master devで下記のようになってくれるとうれしい。

                             x'---y'(subdev)
                            /
A---B---C(master)---1'---2'---3'(dev)

だが、実態はそうではない。以下で試してみる。まず準備。

#devブランチを作成
$ git chb dev
$ touch newfeature
$ git add newfeature
$ git commit -am"Add newfeature"
$ echo "feature is ..." >> newfeature
$ git commit -am "Add message line 1"
#devブランチにサブのブランチを作成し育てる
$ git chb subdev
$ echo "sub module now" >> newfeature
$ git commit -am "Add message line 2(sub module)"
$ echo "sub module now 2" >> newfeature
$ git commit -am "Add message line 3(sub module)"
#devブランチに戻り育てる
$ git ch dev
$ echo "new feature end" >> newfeature
$ git commit -am "Add message line 2"
#masterブランチに戻り育てる
$ git chm
$ echo "feature add" >> num
$ git commit -am "Modify num"
$ echo "feature add 2" >> num
$ git commit -am "Modify num 2"

で、今のグラフ。

$ git g
  y * ebdc7e7  (subdev) Add message line 3(sub module)
C   | * 18ac45f  (HEAD, master) Modify num 2
B   | * a43a699  Modify num
 3  | | * a3f65de  (dev) Add message line 2
  x * | | f473f19  Add message line 2(sub module)
    | |/
    |/|
 2  * | cf36abe  Add message line 1
 1  * | 43b3504  Add newfeature
    |/
A   * 3aec83c  (nobra) Add message nobra

rebase開始。

$ git rebase master dev
First, rewinding head to replay your work on top of it...
Applying: Add newfeature
Applying: Add message line 1
Applying: Add message line 2

グラフはこうなる。

$ git g
 3'  * 948e1a4  (HEAD, dev) Add message line 2
 2'  * 0bc3e36  Add message line 1
 1'  * ae15a29  Add newfeature
   y | * ebdc7e7  (subdev) Add message line 3(sub module)
C    * | 18ac45f  (master) Modify num 2
B    * | a43a699  Modify num
   x | * f473f19  Add message line 2(sub module)
 2   | * cf36abe  Add message line 1
 1   | * 43b3504  Add newfeature
     |/
A    * 3aec83c  (nobra) Add message nobra

(ブランチが)すごく…多いです。こうなった。

           x---y(subdev)
          /
   1---2--
  /
A---B---C(master)---1'---2'---3'(dev)

dev(1,2,3)はきちんと適用された。が、subdev(x,y)は適用されていない。ので1,2,x,yは残っている。(3はdevをrebaseし、subdevから到達できないのでいつもどおり削除されている)

むむむ。しかし、修正内容さえ分かっていればコンフリクトしても冷静に直せばきちんとrebaseできるか。dev(3')にsubdev(y)をrebaseする。

$ git rebase dev subdev
First, rewinding head to replay your work on top of it...
Applying: Add message line 2(sub module)
Using index info to reconstruct a base tree...
Falling back to patching base and 3-way merge...
Auto-merging newfeature
CONFLICT (content): Merge conflict in newfeature
Failed to merge in the changes.
Patch failed at 0001 Add message line 2(sub module)

When you have resolved this problem run "git rebase --continue".
If you would prefer to skip this patch, instead run "git rebase --skip".
To restore the original branch and stop rebasing run "git rebase --abort".

$ vi newfeature
$ git add newfeature
$ git rebase --continue
Applying: Add message line 2(sub module)
Applying: Add message line 3(sub module)
Using index info to reconstruct a base tree...
Falling back to patching base and 3-way merge...
Auto-merging newfeature

$ git g
* 0fe8a57  (HEAD, subdev) Add message line 3(sub module)
* 71f976a  Add message line 2(sub module)
* 948e1a4  (dev) Add message line 2
* 0bc3e36  Add message line 1
* ae15a29  Add newfeature
* 18ac45f  (master) Modify num 2
* a43a699  Modify num
* 3aec83c  (nobra) Add message nobra

rebase対merge

  • 1人1リポジトリとかで作業している場合は、あまり意識せずに自由にやってもいい
    • mergeの方が何をしていたかの履歴が残るので良いかもしれない
  • rebaseを使う時の問題は、複数人複数リポジトリで作業している場合
    • rebaseすると新しいコミットになる(SHA1も変わる)
    • 公開した(pushした)後にrebaseするのはまずい
  • 上記のようにrebaseしたいブランチに依存しているブランチがある場合も注意かもしれない
    • うまくrebaseしていかないとグラフがどうなっているのかわからなくなりそう…
    • マージを含むブランチがある場合のrebaseも同様

*1:Git道場で実施したのはpull --rebaseだけど基本は同じはず

Git道場#1に参加しました と、pullとpull --rebase備忘録 #gitdojo

概要

対象者が

merge / rebaseにちょっと自信がない
conflictが怖い

まさにそんな状況だったので、打破するために参加しました。

心「Git総論、心構え」

Gitにはリモートリポジトリ、ローカルリポジトリがある
Gitは頑健である
Gitは時間的な変遷を管理する
  • 昨日のこの時間何してたかな?
  • testブランチを消してもコミットは残っている
  • 作業履歴が残っているのでreflogで参照できる
    • reflogで救済できる期間は90日以内、またはgit gc が実行されるまで
他(質疑応答の回答など)
  • ブランチを削除してもコミットは残っている。git branch -D
  • GitHub重い……
    • イントラにbareリポジトリ用意して毎朝GitHubから持ってくるなど

技「本日の課題、テクニックの解説」

課題
  • 今日はチームで一つのファイルを編集
  • pull, rebaseを怖がらずに
    • コンフリクトが起こった時の対処法を学ぶ
  • pullとの違いを理解する
    • ≒mergeとrebaseの違いでいいのかな?
ルール
  • 1-10までのNumbersファイルの後ろに記号を追加削除していく
  • コミットメッセージだけで語る
  • チーム間ではコミットメッセージのみを介して会話する
  • 「好きにやっていいので、ぐちゃぐちゃを楽しんでください」
  • 今回は@myfinderさん、@umiyoshさん、@nysalorさんと黙々と。

...みっちり数時間。

  • (グラフが)とても…カオスです
実習後
  • 再び講義。その後、同じNumbersファイルを(まっさらにしてから)やり直し
  • さっきはpullでリポジトリから取得していたと思うけど、今回は必ずpull --rebaseする事
    • コミットを直列にならべる事が目的
git pull --rebase
git add 
git rebase --continue
  • rebaseとは
    • (ざっくりと)コミットをかぶせる
      • リモートの最新コミットにローカルの共通コミットから先のコミットが被せられる(onto)
      • まっすぐになるので誰が何コミットしたかわかりやすい
      • コンフリクトした場合、無名ブランチがチェックアウトされた状態になる
  • 一方でmergeは
    • コミットを統合する(基本的にマージコミットが生まれる=見た感じ複雑)
      • リモートに新しいコミットがあると失敗する
      • 変更履歴が残るので、後で調査がしやすい
  • どちらがいいかは状況次第
    • 他人がコミットしている事を意識する
    • ローカルブランチでは作業履歴を残すためmergeの方がいいかも
アンチパターン
  • git add .
    • 全部追加するとかありえない
    • statusで確認してね
  • 無名ブランチでコミット
    • 困った場合は --abortで中断する
    • git rebase --skipでスキップする事ができる
  • git config user.nameとか設定して

という感じで13:00から18:00までadd,commit,push,pull(pull --rebase), コンフリクト解消を繰り返していました。個人的にはチューターの方にも丁寧に説明していただき、rebaseもかなり腹に落ちた感じで参加してよかった。後はこの感覚があるうちに本で復習してみる。

会場を提供して下さったフューチャーアーキテクトさんとGit道場師範の皆さんありがとうございました。門下生の皆さんお疲れ様でした。(終わった時にはほぼ全員ぐったりしていた)

pull、pull --rebaseまとめ

糞長いので先にまとめ。

pull

以下のふたつのリポジトリがあったとき

A
(FIRST)---(NUMBERADD)
          origin/master
B
(FIRST)---(hello world)---(hello git)---(bye svn)
origin/master

Bがpullするとこういう歴史が出来る。

          (NUMBERADD)----------------------------(merge)
         /                                       /
(FIRST)---(hello world)---(hello git)---(bye svn)
pull --rebase

同じく。

A
(FIRST)---(NUMBERADD)
          origin/master
B
(FIRST)---(hello world)---(hello git)---(bye svn)
origin/master

Bがpull --rebaseするとこういう歴史ができる。

          (NUMBERADD)---(hello world merge)
         /              no branch
(FIRST)---(hello world)---(hello git)---(bye svn)
          (NUMBERADD)---(hello world merge)---(hello git merge)
         /                                    no branch
(FIRST)---(hello world)---(hello git)---(bye svn)
          (NUMBERADD)---(hello world merge)---(hello git merge)---(bye svn merge)
         /                                                        no branch
(FIRST)---(hello world)---(hello git)---(bye svn)
          (NUMBERADD)---(hello world merge)---(hello git merge)---(bye svn merge)
         /                                                        master
(FIRST)--

整形して、

(FIRST)---(NUMBERADD)---(hello world merge)---(hello git merge)---(bye svn merge)
                                                                  master

以下に実際にやってみたログ。

pull

dojo1さんとdojo2さんでdojo.gitリポジトリに書き込んでいく。空のnumファイルをfirst commit後……。

dojo1

dojo1さんが準備。

$ cat num
 1
 2
 3
 4
 5
$ git coa -m "1から5までnumberふり"
[master 27734d8] 1から5までnumberふり
 1 files changed, 5 insertions(+), 0 deletions(-)

グラフはこんな感じ。

$ git g
* 27734d8 2012-04-22 kk_Ataka  (HEAD, master) 1から5までnumberふり
* 9f20959 2012-04-22 kk_Ataka  (origin/master) first commit
dojo2

dojo2さん。cloneしたときはこんなグラフ。

$ git g
* 9f20959 2012-04-22 kk_Ataka  (HEAD, origin/master, origin/HEAD) first commit

ここに27734d8をプルする前にローカルで色々育てる。

$ vim num
$ git coa -m "hello world追加"
$ vim num
$ git coa -m "hello git追加"
$ vim num
$ git coa -m "bye svn追加"

グラフはこう。

$ git g
* 817be9c 2012-04-22 kk_Ataka  (HEAD, master) bye svn追加
* 66d89ab 2012-04-22 kk_Ataka  hello git追加
* cb71f84 2012-04-22 kk_Ataka  hello world追加
* 9f20959 2012-04-22 kk_Ataka  (origin/master, origin/HEAD) first commit

この状態でプルすると…

$ git pull
remote: Counting objects: 5, done.
remote: Total 3 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
From /home/kk_Ataka/github/dojo
   9f20959..27734d8  master     -> origin/master
Auto-merging num
CONFLICT (content): Merge conflict in num
Automatic merge failed; fix conflicts and then commit the result.
[22:54:45 kk_Ataka@www15203u (master *+|MERGING<>)~/github/dojo2]
$ git g
* 817be9c 2012-04-22 kk_Ataka  (HEAD, dojo2/master, master) bye svn追加
* 66d89ab 2012-04-22 kk_Ataka  hello git追加
* cb71f84 2012-04-22 kk_Ataka  hello world追加
| * 27734d8 2012-04-22 kk_Ataka  (origin/master, origin/HEAD) 1から5までnumberふり
|/
* 9f20959 2012-04-22 kk_Ataka  first commit

first commit以降のブランチがdojo1さんが編集したものと自分が育てたものに分岐。これを解消してやり、コミット。

 git coa -m "コンフリクトを解消し、メッセージにnumberをふった"
[master d21349d] コンフリクトを解消し、メッセージにnumberをふった
[22:57:18 kk_Ataka@www15203u (master>)~/github/dojo2]
$ git g
*   d21349d 2012-04-22 kk_Ataka  (HEAD, master) コンフリクトを解消し、メッセージにnumberをふ
|\
* | 817be9c 2012-04-22 kk_Ataka  (dojo2/master) bye svn追加
* | 66d89ab 2012-04-22 kk_Ataka  hello git追加
* | cb71f84 2012-04-22 kk_Ataka  hello world追加
| * 27734d8 2012-04-22 kk_Ataka  (origin/master, origin/HEAD) 1から5までnumberふり
|/
* 9f20959 2012-04-22 kk_Ataka  first commit
dojo1に戻り

dojo1に戻りプルして一行追加しコミット&プッシュ。

$ git pull
remote: Counting objects: 16, done.
remote: Compressing objects: 100% (4/4), done.
remote: Total 12 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (12/12), done.
From /home/kk_Ataka/github/./dojo
   27734d8..d21349d  master     -> origin/master
Updating 27734d8..d21349d
Fast-forward
 num |    6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)
$ git g
*   d21349d 2012-04-22 kk_Ataka  (HEAD, origin/master, master) コンフリクトを解消し、メッセ
|\
* | 817be9c 2012-04-22 kk_Ataka  bye svn追加
* | 66d89ab 2012-04-22 kk_Ataka  hello git追加
* | cb71f84 2012-04-22 kk_Ataka  hello world追加
| * 27734d8 2012-04-22 kk_Ataka  (dojo1/master) 1から5までnumberふり
|/
* 9f20959 2012-04-22 kk_Ataka  first commit
$ vim num
$ git coa -m "number6を追加"
[master eeeab6f] number6を追加
 1 files changed, 1 insertions(+), 0 deletions(-)
$ git push
Counting objects: 5, done.
Writing objects: 100% (3/3), 294 bytes, done.
Total 3 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
To /home/kk_Ataka/github/./dojo.git/
   d21349d..eeeab6f  master -> master
同じ頃dojo2では

その隙にdojo2は少しローカルで育て中。(ただし、今度はコンフリクトさせないように)

$ vi num
$ git coa -m "bye svnは削除"

そしてさっきのdojo1の更新をプル。

$ git pull
remote: Counting objects: 5, done.
remote: Total 3 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
From /home/kk_Ataka/github/dojo
   d21349d..eeeab6f  master     -> origin/master
Auto-merging num
Merge made by recursive.
 num |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)
[23:06:42 kk_Ataka@www15203u (master>)~/github/dojo2]
$ git g
*   5ba127c 2012-04-22 kk_Ataka  (HEAD, master) Merge branch 'master' of /home/kk_Ataka/gith
|\
* | 252d4b5 2012-04-22 kk_Ataka  bye svnは削除
| * eeeab6f 2012-04-22 kk_Ataka  (origin/master, origin/HEAD) number6を追加
|/
*   d21349d 2012-04-22 kk_Ataka  コンフリクトを解消し、メッセージにnumberをふった
|\
* | 817be9c 2012-04-22 kk_Ataka  (dojo2/master) bye svn追加
* | 66d89ab 2012-04-22 kk_Ataka  hello git追加
* | cb71f84 2012-04-22 kk_Ataka  hello world追加
| * 27734d8 2012-04-22 kk_Ataka  1から5までnumberふり
|/
* 9f20959 2012-04-22 kk_Ataka  first commit

こうなる。なので基本的にプルはマージの履歴が残る。

pull --rebase

pull --rebaseではどうか。下記の状態まで戻る。

dojo1
$ git g
* 49622c6 2012-04-22 kk_Ataka  (HEAD, origin/master, master) 1から5までnumberふり
* ec12cb5 2012-04-22 kk_Ataka  first commit
dojo2
$ git  g
* 3a940bc 2012-04-22 kk_Ataka  (HEAD, master) bye svn追加
* 763cbaa 2012-04-22 kk_Ataka  hello git追加
* d6c6c98 2012-04-22 kk_Ataka  hello world追加
* ec12cb5 2012-04-22 kk_Ataka  (origin/master, origin/HEAD) first commit

ここでpull --rebaseを使う。

$ git pull --rebase
remote: Counting objects: 5, done.
remote: Total 3 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
From /home/kk_Ataka/github/dojo
   ec12cb5..49622c6  master     -> origin/master
First, rewinding head to replay your work on top of it...
Applying: hello world追加
Using index info to reconstruct a base tree...
Falling back to patching base and 3-way merge...
Auto-merging num
CONFLICT (content): Merge conflict in num
Failed to merge in the changes.
Patch failed at 0001 hello world追加

When you have resolved this problem run "git rebase --continue".
If you would prefer to skip this patch, instead run "git rebase --skip".
To restore the original branch and stop rebasing run "git rebase --abort".

盛大にコンフリクトする。改めて見るとrebase --continue, --skip, --abortを使いなさいって書いてあるな。

で、今のrebaseが始まったとき、ブランチはどこにいるのかというと……。

$ git br
* (no branch) 49622c6 1から5までnumberふり
  master      3a940bc [ahead 3, behind 1] bye svn追加

ここ。無名ブランチ。この496...はどこかというと……。

$ git g
* 3a940bc 2012-04-22 kk_Ataka  (master) bye svn追加
* 763cbaa 2012-04-22 kk_Ataka  hello git追加
* d6c6c98 2012-04-22 kk_Ataka  hello world追加
| * 49622c6 2012-04-22 kk_Ataka  (HEAD, origin/master, origin/HEAD) 1から5までnumberふり
|/
* ec12cb5 2012-04-22 kk_Ataka  first commit

dojo1さんがプッシュしていた所。なにはともあれまず、リポジトリにプッシュされていたものを優先する。このdojo1さんの変更に対して、d6c6c98、763cbaa、3a940bcとひとつずつrebaseしていく。問題を解決したらrebase --continue。無名ブランチにいるのでコミットしちゃダメ。

$ vim num
競合解消…
$ git add num
$ git rebase --continue
Applying: hello world追加
Applying: hello git追加
Using index info to reconstruct a base tree...
Falling back to patching base and 3-way merge...
Auto-merging num
CONFLICT (content): Merge conflict in num
Failed to merge in the changes.
Patch failed at 0002 hello git追加

ひとつ解消したらふたつ目でまたコンフリクトした。今どこにいるかというと……。

$ git br
* (no branch) 781c723 hello world追加
  master      3a940bc [ahead 3, behind 1] bye svn追加
$ git g
* 781c723 2012-04-22 kk_Ataka  (HEAD) hello world追加
| * 3a940bc 2012-04-22 kk_Ataka  (master) bye svn追加
| * 763cbaa 2012-04-22 kk_Ataka  hello git追加
| * d6c6c98 2012-04-22 kk_Ataka  hello world追加
* | 49622c6 2012-04-22 kk_Ataka  (origin/master, origin/HEAD) 1から5までnumberふり
|/
* ec12cb5 2012-04-22 kk_Ataka  first commit

コンフリクトを解消しつつ無名ブランチで突き進んでいる。

$ vim num
競合解消…
$ git add num
$ git rebase --continue
Applying: hello git追加
Applying: bye svn追加
Using index info to reconstruct a base tree...
Falling back to patching base and 3-way merge...
Auto-merging num
CONFLICT (content): Merge conflict in num
Failed to merge in the changes.
Patch failed at 0003 bye svn追加

どんどん無名ブランチを進めていく。

$ git br
* (no branch) 8fb0d5e hello git追加
  master      3a940bc [ahead 3, behind 1] bye svn追加
$ git g
* 8fb0d5e 2012-04-22 kk_Ataka  (HEAD) hello git追加
* 781c723 2012-04-22 kk_Ataka  hello world追加
| * 3a940bc 2012-04-22 kk_Ataka  (master) bye svn追加
| * 763cbaa 2012-04-22 kk_Ataka  hello git追加
| * d6c6c98 2012-04-22 kk_Ataka  hello world追加
* | 49622c6 2012-04-22 kk_Ataka  (origin/master, origin/HEAD) 1から5までnumberふり
|/
* ec12cb5 2012-04-22 kk_Ataka  first commit

解消。

$ vim num
競合解消…
$ git add num
$ git rebase --continue
Applying: bye svn追加

これで全てのコミットの変更がdojo1さんの変更の上に適用された。で、今どこにいるかというと。

$ git br
* master 96897da [ahead 3] bye svn追加
$ git g
* 96897da 2012-04-22 kk_Ataka  (HEAD, master) bye svn追加
* 8fb0d5e 2012-04-22 kk_Ataka  hello git追加
* 781c723 2012-04-22 kk_Ataka  hello world追加
* 49622c6 2012-04-22 kk_Ataka  (origin/master, origin/HEAD) 1から5までnumberふり
* ec12cb5 2012-04-22 kk_Ataka  first commit

無名ブランチからmasterブランチに。自分で作っていたコミットはなくなりあたらしくdojo1さんが作ったコミットの先に移動している。(SHA1が違う)

ZenTestで実行したRSpecの結果をGrowlで通知してくれるようにした

前回までのあらすじ

前回は、ファイル編集する -> alt+tabでウィンドウ切り替える -> プロンプトでrspecコマンドうつ…の繰り返しを改善することができた。
今回は、コード修正、保存 -> 違うターミナル切り替え -> ZenTestで自動実行された結果を見る…の繰り返しを改善する。テスト結果通知にGrowlを使用する事でいけそう。

環境

Macに置き換えてもいけるかは後で確認。

手順

Growls for Windowsインストール
Gem入手
  • Gemfileファイルを作って以下のgemファイルを記載
gem 'ZenTest'
gem 'autotest-growl'
  • bundle install
.autotest
  • 前回何も記載しなかった.autotestファイルに以下を追記。
require 'autotest/growl'
実行
$ bubdle exec autotest
loading autotest/rspec2


--------------------------------------------------------------------------------

[2J[fC:\rubies\Ruby-193-p0\bin\ruby -rrubygems -S C:/WINDOWS/my/project/sha1/vendor/bundle/ruby/1.9.1/gems/rspec-core-2.8.0/exe/rspec --tty 'C:/WINDOWS/my/project/sha1/spec/sha1_spec.rb'
.......

Finished in 0.03125 seconds
7 examples, 0 failures

と同時にGrowlポップアップきたこれ! 意外とすぐだった!

以下いろいろと失敗の試行錯誤Log

Windows用でないとダメみたい?
+ 3 source "http://gems.github.com"
  8 gem 'ZenTest'
- 9 gem 'autotest-growl'
+ 9 gem 'karl-autotest-growl'
  • bundle install
  • bubdle exec autotest
ZenTest実行されなくなった…
- 8 gem 'ZenTest'
+ 9 gem 'autotest'
+10 gem 'autotest-growl'
+11 gem 'autotest-fsevent'

fseventをインストールするにはDevelopment kitが必要らしい。Rails3レシピブックを読みながらRailsを学ぶ - kk_Atakaの日記 インストール方法。

で、.autotestに追加。

+ require 'autotest/fsevent'

Subversionで2ヶ所のリポジトリの同期を取るメモ

前提

差分のdumpとってload(失敗)

Aサーバ
  • 進んでいる分のダンプを取る。
    • rオプションでダンプを取るリビジョンを指定できる。一つだけだとそのリビジョンだけ。(222ならリビジョン222)範囲指定する場合はAAA:BBBとする
$ svnadmin dump リポジトリパス(/home/xxx/yyyなど) -r 111:222 --incremental > repo.dump
  • これをなんらかの方法でBサーバへ移動する(ftpでもUSBでも)
Bサーバ
  • svnadmin loadコマンドで差分ダンプファイルを流しこむ。
    • リビジョンがかぶっているとエラー(リビジョン111未満のもの)
$ svnadmin load リポジトリパス(/home/xxx/yyyなど) < repo.dump
<<< オリジナルのリビジョン 111 に基づき、新しいトランザクションを開始しました
     * パスを追加しています : trunk/xxx ...svnadmin: ファイルが既に存在します: ファイルシステム 'リポジトリパス', トランザクション xxx-xx, パス 'trunk/xxx'
    • 112からダンプしたファイルをloadする…とうまくいく予定だったのだが、なんかファイルのチェックサムが違うといわれた……。
$ svnadmin load リポジトリパス(/home/xxx/yyyなど) < repo.dump
<<< オリジナルのリビジョン 112 に基づき、新しいトランザクションを開始しました
     * パスを編集しています : trunk/xxx/a.sh ... 完了しました。

------- 新しいリビジョン xxx を (オリジナルのリビジョン xxx からロードして) コミットしました >>>

<<< オリジナルのリビジョン 113 に基づき、新しいトランザクションを開始しました
     * パスを編集しています : trunk/xxx/b.sh ... 完了しました。
     * パスを編集しています : trunk/xxx/c.sh ...
     svnadmin: ファイル '/trunk/xxx/c.sh' のチェックサムが一致しませんでした:
   期待:  f566e489511cea2fd1e6 ...
   実際:  0f76ab4f5d0625e9de9c ...

フルダンプをとる => 新しくリポジトリを作成 => loadでも同じファイル(リビジョンは違った)でコケたので別の方法を考える……。

hotcopy(成功)

このサブコマンドは、すべてのフック、設定ファイル、そしてもちろんデータベースファイルを含む、リポジトリの完全な「ホット」バックアップを作成します。

http://www.caldron.jp/~nabetaro/svn/svnbook-1.4-final/svn.ref.svnadmin.c.hotcopy.html

ただし可搬性に乏しいとの事。今回は同マシン、OS、Subversionバージョンなので大丈夫だと思う。まずAサーバでコピー。

$ svnadmin hotcopy リポジトリパス(/home/xxx/yyyなど) コピー先のリポジトリパス
a /home/xxx/yyy OK
a /home/xxx/yyy/hooks OK
a /home/xxx/yyy/hooks/start-commit.tmpl 3K
...
a /home/xxx/yyy/format 1K

これをBサーバへ持ってくるだけ。フルバックアップしかできないのでこれしか方法はない?

とりあえず一時しのぎはできたけど、チェックサム解消法も考えないといけないな。

Pro Gitと入門Gitと入門gitでGitの復習 HEADのキャレットとかチルダとか補講編

前回までのあらすじ

GitHubで他の人の.gitconfigとかを見たりすると、HEAD^とかHEAD~~とかにエイリアスが貼ってあるけど、これってなんなの?
今の認識: 書いた分だけリビジョンが戻ってくれる程度

参考

調査

入門Git P87 コミットの祖先の指定によると、

記法 意味
^ 指定したコミットの1番目の親
^番号 指定したコミットのN番目の親
~ 指定したコミットの1世代前の親
~世代 指定したコミットのN世代前の親

という事らしい……が、番目と世代は何が違うんだろう? とりあえずこんな歴史があるとして、masterから戻ってみる。

確認
* b467307 2012-04-05 kk_Ataka  (HEAD, origin/master, master) Add get_sheetname.rb(convert exe file b
| * b025b6b 2012-04-05 kk_Ataka  (1.0stable, fileignore) Ignore docx files
* |   90aaa1c 2012-04-04 kk_Ataka  Merge branch 'studyissue'
|\ \
* | | 2d387ba 2012-04-04 kk_Ataka  (concat) Add concat function (test pending...)
* | | 68ac3d9 2012-04-04 kk_Ataka  Add csv concat
* | | 9a4ed9b 2012-04-04 kk_Ataka  Move input cell(ex:B2) downcase(b2) in cell_reg_check and cell_to
| * | 670d891 2012-04-04 kk_Ataka  (studyissue) Move comment, source to readme
|/ /
* | d0f2b58 2012-04-04 kk_Ataka  Refactoring now
|/
* 0563594 2012-04-04 kk_Ataka  1.0stable
* 3d2f6bb 2012-04-04 kk_Ataka  First commit

まず一番目の親を指定……。

$ git checkout HEAD^
...
HEAD is now at 90aaa1c... Merge branch 'studyissue'

うん、指定できてる。んじゃ一旦masterに戻って、次はキャレット連発で。二つ前を指定できるはず。

$ git checkout HEAD^^
...
HEAD is now at 2d387ba... Add concat function (test pending...)

読み通り。じゃあ次は^NでN番目の親を指定してみる。

$ git checkout HEAD^2
error: pathspec 'HEAD^2' did not match any file(s) known to git.

あ、あれ?

$ git checkout HEAD^3
error: pathspec 'HEAD^3' did not match any file(s) known to git.

ん?

$ git checkout HEAD^1
...
HEAD is now at 90aaa1c... Merge branch 'studyissue'

これはできるの? ふーむ。


(以下略)


結局こうなった。

* b467307       master(HEAD)
| * b025b6b   
* |   90aaa1c   HEAD^     HEAD^1 HEAD~     HEAD~1
|\ \  
* | | 2d387ba   HEAD^^           HEAD~~    HEAD~2
* | | 68ac3d9   HEAD^^^          HEAD~~~   HEAD~3
* | | 9a4ed9b   HEAD^^^^         HEAD~~~~  HEAD~4
| * | 670d891          
|/ /                   
* | d0f2b58     HEAD^^^^^        HEAD~~~~~ HEAD~5
|/
* 0563594 
* 3d2f6bb 

うーむ。戻れるのはわかったけど、2つわからんとこが残る。。。

  • 番目と世代前の違い
  • ^^と^2の違い
本に戻ってみる

入門Gitを少し読み進める。

大多数のコミットには親が1つしかありませんが、マージコミットには
親が複数あります。

マージする以前のホームマシンの作業リポジトリの先頭のコミットがHEAD^、
一方、マージしたコミットはHEAD^2ということになります。

……入門gitでは

^:キャレットはマイナス1の意味だ。18f822e^は18f822eに
マッチするリビジョンの前にあるリビジョンとして解釈される。

~N:チルダと数字Nは、そのコミット名からNだけ前に戻る。前の例だと
18f822e~1は18f822eの前のリビジョン、18f822e~2は18f822eの2つ前の
リビジョンだ。

親が複数ある状況を作らないといけないという事かな。

再度チャレンジ

少し適当にコミットしてマージして親が2つある状況を作った。

*   8dc8247 2012-04-10 kk_Ataka  (HEAD, master) Merge branch 'mergedbranch'
|\
* | ca6b93d 2012-04-10 kk_Ataka  (mergedbranch2) temp
* | 7819449 2012-04-10 kk_Ataka  temp
| * 074c658 2012-04-10 kk_Ataka  (mergedbranch) temp
* | b467307 2012-04-05 kk_Ataka  (origin/master) Add get_sheetname.rb(convert exe file by ocra
|/
| * b025b6b 2012-04-05 kk_Ataka  (1.0stable, fileignore) Ignore docx files
* |   90aaa1c 2012-04-04 kk_Ataka  Merge branch 'studyissue'
$ git ch HEAD^
...
HEAD is now at ca6b93d... temp

これはできると。んで、問題の^2は……

$ git ch HEAD^2
...
HEAD is now at 074c658... temp

できた! ってことは、二つのブランチしかマージしていないから、^3はエラーになるはず……。

$ git ch HEAD^3
error: pathspec 'HEAD^3' did not match any file(s) known to git.

おー。

*   8dc8247     master(HEAD)
|\
* | ca6b93d     HEAD^    HEAD^1  HEAD~    HEAD~1
* | 7819449     HEAD^^           HEAD~~   HEAD~2
| * 074c658              HEAD^2
* | b467307     HEAD^^^          HEAD~~~  HEAD~3
|/            
| * b025b6b   
* |   90aaa1c   HEAD^^^^ HEAD^2^ HEAD~~~~ HEAD~4

                  (ERROR:HEAD^3)

んん? ^Nはわかったけど、^^と^2の違いが余計わからなくなった……。

あ! HEAD^2^という合わせ技ができたって事はもしかして……。

まとめ

コマンド 意味 備考
HEAD^ 指定したコミットの1番目の親 ※1
HEAD^^ 指定したコミットの1番目の親…の1番目の親 ※2
HEAD^^^ 指定したコミットの1番目の親…の1番目の親の1番目の親 ※3
HEAD^2 指定したコミットの2番目の親
HEAD^2^ 指定したコミットの2番目の親…の1番目の親
HEAD~ 指定したコミットの1世代前の親 ※1
HEAD~~ 指定したコミットの1世代前の親…の1世代前の親 ※2
HEAD~~~ 指定したコミットの1世代前の親…の1世代前の親…の1世代前の親 ※3
HEAD~1 指定したコミットの1世代前の親 ※1
HEAD~2 指定したコミットの2世代前の親 ※2
HEAD~3 指定したコミットの3世代前の親 ※3

※1 ※2 ※3 は同じリビジョン

こういう事かな。あっているならチェックアウトの挙動と一致するのだけど!

VimでBundler(プラグイン管理)するvundleインストール手順

前回までのあらすじ

普通に使っているだけだった。プラグインとかも使ってみたい、入れ方メモる。

環境

  • WindowsXP
  • Vim 7.3 香り屋版
  • msysGit

プラグイン管理

プラグインを入れようと思った矢先、どうもプラグイン管理をするプラグイン? がある模様。名前がvundleといって、RubyのGem管理に使われているBundlerに影響を受けたものみたい。Bundlerなら使ったことあるし、それなら入れやすいかも。

vundleインストール

Githubリポジトリがあるのでgitでホームの.vimディレクトリにcloneする。

$ git clone http://github.com/gmarik/vundle.git ~/.vim/vundle.git
Cloning into %USERPROFILE%/.vim/vundle.git...
remote: Counting objects: 2239, done.
remote: Compressing objects: 100% (1464/1464), done.
remote: Total 2239 (delta 736), reused 2183 (delta 685)
Receiving objects: 100% (2239/2239), 269.48 KiB | 66 KiB/s, done.
Resolving deltas: 100% (736/736), done.
設定

_vimrcまたは.vimrcを開き、まず以下の設定を記載。

" vundle
set nocompatible
filetype off
set rtp+=~/.vim/vundle.git
call vundle#rc()

filetype plugin indent on

一行目のnocompatible……。

NOTE: Viコンパチブルとは全てのオプションがグローバルであることを意味するので、
ファイル形式識別と'compatible'は同時に使うことはできない。既に'compatible'を設
定している場合には、それを解除する必要がある。

という事でファイル形式の検出と競合するので無効にされている模様。で、ファイル形式の検出はfiletypeコマンドで設定される。vimはファイル編集の際に必ずファイルタイプを検出し、いい感じのタイプを選んでくれるらしい。大きく分けて下記の3つの設定がある。

  • 検出自体をするかどうか
    • プラグインを検出するかどうか
    • インデントファイルを検出するかどうか

検出自体するかどうかが一番強く、これが無効になると残りも自動的に無効になるようだ。

上記の.vimrcではこのように変化している。

コマンド 検出 プラグイン インデント
:filetype off 無効 変化なし 変化なし
:filetype plugin indent on 有効 有効 有効

また、:filetypeコマンドで現在の状態を確認する事ができる。

filetype detection:ON  plugin:ON  indent:OFF

rtpがなんなのかわからないけど、とりあえずこれにvundle.gitのパスを追加? した後vundle#rcを呼んでる。vundle#rcメソッドはvundle.git/autoload/vundle.vimにあった。

func! vundle#rc(...) abort
  let g:bundle_dir = len(a:000) > 0 ? expand(a:1    , 1) : expand('$HOME/.vim/bundle', 1)
  let g:vundle_log = []
  call vundle#config#init()
endf

vundleの初期化を行っているようだ。

プラグインの指定

実際にインストールするプラグインはvundle#rc()とfiletypeの間に記載していく。プラグインの指定方法は三つあり、書き方で自動判別してくれる?

Bundle 'user_name/repository_name'
Bundle 'git://repository_url'
Bundle 'plugin_name'

今回は補完を行うneocomplecacheというプラグインをインストールしてみる。Shougo/neocomplcache · GitHub GitHubにあるので……。

" vundle
set nocompatible
filetype off
set rtp+=~/.vim/vundle.git
call vundle#rc()

Bundle 'Shougo/neocomplcache'

filetype plugin indent on

こうなる。これで:BundleInstallをすればいいんだけどその前に!

Windows環境で必須なもの

Vundle for Windows · gmarik/vundle Wiki · GitHub
Gitとcurlが必要だったようで。Gitは入っていたがcurlが入っていなかったので入れる。

……というか、msysGitの中にcurlコマンドがあるのでそれを使えた。もしくは上記のページにあるcmdファイルを作成する。

httpで落としたい

Git://とかhttps;//が使えない場合、http://で落としたいんだけど、GitHub指定方法だとhttps://でgit cloneしようとしてうまくいかない。

じゃあフルパス指定したらいけるかなと思ってこうしてみた。

Bundle 'http://github.com/Shougo/neocomplcache'

これでもhttps://でcloneされてしまう。困ったのでソースを見てみたら案外早く解決方法見つかった。.vim/vundle.git/autoload/vundle/config.vimの44行目くらいにプロトコルを指定しているところが。

 let git_proto = exists('g:vundle_default_git_proto') ? g:vundle_default_gi
 t_proto : 'https'

これをhttpにしてみたらDone!になった! .vim/bundle/の下にプラグインが!

neocomplcache

.vim\bundle\neocomplcache\doc\neocomplcache.txtのEXAMPLES *neocomplcache-examples*より下を.vimrcにコピー。で、viを再起動したら補完が!