沒穿方服

索引

顯示╱隱藏內文

簡言之,編輯完衝突的檔案、用 add stage 起來後,下一步應該是 rebase --continue 才對; 但我一直是 commit,然後才 rebase --continue,大錯啊!

學習 rebase 時一直疑惑「fix conflicts and then run "git rebase --continue」裡的「fix conflicts」到底是什麼動作,最後試出來是 git commit(錯),就一直錯到現在。


示範一下 commitrebase --continue 誤用的慘狀。

  1. 我在 upstream branch。
    Log 最下面的 commit 是沒問題的,但上面兩個 commit 等下會有衝突。
    註:純 demo 方便,通常不會在 upstream 作 rebase

    upstream 的 log
  2. 另一個 branch demo,我做了一個 commit,等下 rebase 時會衝突。

    demo branch 的 log
  3. 開始 git rebase -i demo,果然衝了。

    進行 rebase,產生衝突

    出現 git 提示「fix conflicts and then run "git rebase --continue」。

  4. 手動編輯衝突的檔案(解除衝突),過程省略。

  5. git add . 把解好的部分 stage 起來,到此為止的步驟都沒有問題。

    將檔案 stage 起來,視為已手動解完衝突
  6. 錯誤的做法:git commit
    會進入編輯訊息畫面,預設訊息還會附上 Conflicts: src/vars.js

    使用 git commit 時的 commit 訊息編輯畫面

    雖然覺得奇怪(不是解了嗎?)但習慣後就不會再卡了,還會視情況把 Conflicts: 部分刪掉……

  7. git commit 的結果:

    commit 後的結果

    糟糕的事發生了,author 和 committer 都變成我了,這不能接受啊!

    git 用這麼久,怎麼可能沒發現呢?
    其實印象中有幾次 rebase 後作者變成我,覺得很怪就沒 push 出去,但發生次數很少,大概是不常收 pull request、解衝突時幾乎 author 都是自己吧。

  8. 正確做法 git rebase --continue 後的預設訊息。

    使用 git rebase --continue 時的 commit 訊息編輯畫面

    不但沒有 Conflicts:,也有顯示原作者是誰。

  9. 正確結果,committer 是我,但 author 保持不變。

    continue 後的結果

git config 調整

Git 2.0 RC 1 了,確認一下 push.default 設定。

[push]
  ; git 2.0 以前預設為 matching, 會將所有同名 branch push 出去
  ; git 1.7.6 以前可以用 tracking (deprecated),等於後來的 upstream
  ; git 1.7.11 開始可以使用 simple,即 2.0 預設值
  default = tracking
  default = simple

參考 git-config Documentationpush.default 條。 進行 git push,沒指定 refspec 時,舊預設值 matching 會把 local 的所有 branch,只要 remote 有一樣名字的就推出去。 但通常我們只會改一個 branch,也只有這個 branch 是要給別人看的,如果意外把其它 local branch 也推出去就糟了。 所以選 simple 比較適合,會先試 upstream 的作法把「目前的」branch 推到它的 upstream(可以用 git branchgit push--set-upstream 設定,或直接在 .git/config 中設 [branch.foo] 的 remote);如果 git 找不到已知的 upstream,會再嘗試 current 作法,推到與目前 branch 同名的 branch。


看過 doc 後也順便改了:

  • Config 的各個 key 不分大小寫,但預設產生的是全小寫,於是手動改成 camelCase。
  • [log]
      abbrevCommit = true

    只顯示 hash 的前幾個字,這樣 tmux copy-mode 複製時,用 word selection 取到的東西比較簡短。

  • git branch 的 alias 預設加上 --verbose 選項。

    zshrc:

    alias gitb='git branch -v'

    git branch -v

移除 Web Developer 後發現少了「清除 domain cookie」功能,於是補寫一個 FireGestures script,設定為 ← ↓ → ↑ ↓ (LDRUD)Cookie、上下為關閉)取代之。

先詢問再砍 結束時 alert 找不到 domain cookie 時

// Require Firefox 17
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
Cu.import("resource://gre/modules/Services.jsm");

var
  manager = Services.cookies,
  prompter = Services.prompt,
  hostname = gBrowser.currentURI.host,
  cookies = manager.getCookiesFromHost(hostname),
  cookie,
  dialogTitle = 'FireGestures script',
  kills = [];

while (cookies.hasMoreElements()) {
  cookie = cookies.getNext().QueryInterface(Ci.nsICookie2);
  if (cookie.rawHost === hostname || hostname.endsWith('.' + cookie.rawHost)) {
    kills.push(cookie);
  }
}


if (kills.length) {
  if (prompter.confirm(
        null,
        dialogTitle,
        [
          hostname,
          '移除 ' + kills.length + " 個曲奇?",
          "\n  " + kills.map(function (cookie) { return cookie.name; }).join("\n  ")
        ].join("\n")
      )) {
    kills.forEach(function (cookie) {
      manager.remove(
        cookie.host,
        cookie.name,
        cookie.path,
        false
      );
    });
    window.alert('已移除 ' + kills.length + " 個曲奇。");
  }
} else {
  prompter.alert(
    null,
    dialogTitle,
    hostname + "\n沒有需移除的曲奇。"
  );
}

Gblame 運用

Gblame 是什麼

tpope/vim-fugitive 提供的指令,把 git blame 結果顯示在分割視窗。
裡面按 -~P 可以對其它版本再 blame(詳見 doc),比直接在 command line 操作方便多了。

Gblame 畫面


開啟後自動 resize 到作者名

:Gblame 打開後,預設會顯示到 Date,很佔畫面,按 A 可以縮到 Author。

煩的是沒有選項能自動這件事,只好另設一個 command,在 :Gblame 後多送一個 A

command! -nargs=0 GBlameA Gblame | call <SID>fugitiveblame_after()
function! s:fugitiveblame_after() "{{{
  call feedkeys('A')
endfunction "}}}

然後用 tyru/vim-altercmd 方便輸入……

AlterCommand gb[lame] GBlameA

bling/vim-airline 狀態列

很微小的修改,原本狀態列會顯示 fugitive tmp file 的名稱,我把它改成 "Gblame"。

function! AirlineGblame(...)
  if &filetype == 'fugitiveblame'
    let w:airline_section_a = ''
    let w:airline_section_b = ''
    let w:airline_section_c = 'Gblame'
    let w:airline_section_y = ''
  endif
endfunction
let g:airline_statusline_funcrefs = []
call airline#add_statusline_func('AirlineGblame')

Git compare

配合 bootleq/vim-gitdiffall 使用, 按 gf 將檔案變更以 vim diff 開在新 tab,看那個 revision 改了什麼:

gitdiffall 開在新 tab

<LocalLeader>gf 則是開啟新的 tmux window,把該版本變更的檔案全部打開:

gitdiffall 開在新的 tmux window

function! s:fugitiveblame_gitdiffall(all) "{{{
  let rev = matchstr(getline('.'), '\v^\w{7}')
  let buffer = fugitive#buffer(bufname(b:fugitive_blamed_bufnr))
  if a:all
    call TmuxNewWindow({
          \   "text": "gitdiffall @" . rev,
          \   "title": '⎇',
          \   "directory": buffer.repo().tree()
          \ })
  else
    execute printf("tabnew %s | silent GitDiff @%s", buffer.path(), rev)
  endif
endfunction "}}}

autocmd! my_vimrc FileType fugitiveblame
      \ nnoremap <buffer> gf :call <SID>fugitiveblame_gitdiffall(0)<CR> |
      \ nnoremap <buffer> <LocalLeader>gf :call <SID>fugitiveblame_gitdiffall(1)<CR>
function! TmuxNewWindow(...) "{{{
  let options = a:0 ? a:1 : {}
  let text = get(options, 'text', '')
  let title = get(options, 'title', '')
  let directory = get(options, 'directory', getcwd())
  let cmd = 'tmux new-window -a '
        \ . (empty(title) ? '' : printf('-n %s', shellescape(title)))
        \ . printf(' -c %s', shellescape(directory))
  call system(cmd)
  if !empty(text)
    let cmd = printf('tmux set-buffer %s \; paste-buffer -d \; send-keys Enter', shellescape(text))
    call system(cmd)
  endif
endfunction "}}}

這裡比較悶的是 Gblame 的 mapping 都寫死死,最後只好選 gf 來用。
看 issue 感覺是 tpope 不大想理 mapping 的彈性。

一、tpope/vim-rails

我最常用的是 :RT:Tmodel foo:A


二、basyura/unite-rails

可設定按下 ,fR 就打開 Unite 介面,選擇 Rails 相關的 source。

nnoremap [unite] <Nop>
nmap <LocalLeader>f [unite]
nnoremap <silent> [unite]R :<C-U>Unite -start-insert -input=rails/ source<CR>

於是按下 ,fR 就顯示
Unite rails/xxx

接著選擇 initializer,就能進入 rails/initializer 這個 source 的畫面了。
※下圖我按了 ke 示範一下 filter 功能
搜尋 initializers


這兩個 plugin 的功能都不限於「尋找檔案」,這篇就不多說了。