プロジェクト以下ならどこからでも実行できるコマンドなどで、ルートディレクトリからの相対 Path で決まったディレクトリやファイルを取得したい時があったりしました。

$ git rev-parse --show-toplevel
/Users/user/dirname

誰か他の人が削除したか何かでローカルにリモートブランチへの参照が残ってしまった場合。

 git fetch --prune
 # or git remote prune origin

常にそういう参照を削除するようにする

以下のように設定するとfetchだけでfetch --pruneと同じことがされるようになります。

git config --global fetch.prune true

これで取得できます。

git tag --sort=-taggerdate | sed -n 1p

--sort=-taggerdateでタグを付けた日が新しい→古い順に並び替えができます。それをsedで最初の1行目だけにしているだけです。

$ git tag 1
$ git tag 2
$ git tag 2
$
$ git tag
1
2
3
$ git tag --sort=-taggerdate
3
2
1
$ git tag --sort=-taggerdate | sed -n 1p
3

原因

新しい参照を作る時に出た422(Unprocessable Entity)エラーは、ブランチ名をパスで見た時に親の名前でブランチを作ろうとしている為です。
既にディレクトリがある場所に同名でファイルは作れないように、参照はディレクトリの構造で管理されているので同じように参照ファイルを作ることができません。

再現

git push origin master:parent/child
# Total 0 (delta 0), reused 0 (delta 0)
# To github.com:nju33/playground.git
#  * [new branch]      master -> parent/child
# 
git push origin master:parent
# Total 0 (delta 0), reused 0 (delta 0)
# To github.com:nju33/playground.git
#  ! [remote rejected] master -> parent (cannot lock ref 'refs/heads/parent': 'refs/heads/parent/child' exists; cannot create 'refs/heads/parent')
# error: failed to push some refs to 'git@github.com:nju33/playground.git'
ls -l .git/refs/remotes/origin
# drwxr-xr-x  3 nju33  staff  102 Aug 29 14:33 parent
echo a > .git/refs/remotes/origin/parent
# An error occurred while redirecting file '.git/refs/remotes/origin/parent'
# open: Is a directory

大抵はこれで持ってくるはずです。

git clone 

これに、-bオプションと保存先ディレクトリを指定してあげるだけです。

git clone -b   

そのブランチ情報だけ持ってくる

--single-branchを指定するとリモート上のブランチなどを取ってこなくなります。 これでクローンしてくると、.git/configファイルが以下のようになっています。

[remote "origin"]
        url = 
        fetch = +refs/heads/fix/:refs/remotes/origin/fix/

これが作業ブランチだとして、masterブランチだけは定期的に取り込むために参照したいような場合は、このファイルのfetchを追加します。

[remote "origin"]
        url = 
        fetch = +refs/heads/:refs/remotes/origin/
        fetch = +refs/heads/master:refs/remotes/origin/master

これでfetchすれば取ってこれると思います。

$ git fetch
$ git branch -a
* 
  remotes/origin/
  remotes/origin/master
# .git/modules/ を削除
git submodule deinit  
#  を消して、.gitmodulesからも情報をさく削除
git rm  
# (今度はdevelopブランチで)再度追加
git submodule add -b develop  

git rm を先にやってしまった場合は、git submodule add -fとすれば大丈夫です。  

やりたくなった理由

マークアップ系がコンフリクトを起こしてるけど、編集したのは自分じゃないし解決する自信あまりない。でもマージもできないのでCSSファイルなどを持ってきてUIを見ながら修正することもできない。
調べるとCSS関連のファイルではコンフリクトは起きてないので、これだけ持ってきちゃいたい。

それワンライナーでできます

for file in `git diff <比較ブランチ> --name-only | grep .css`; do git checkout develop $file; done

少し解説

  1. git diff --name-onlyはファイル名だけを羅列するのでそれをgrepでほしいファイルだけに絞り込み

  2. git checkout <とあるブランチ> <filename>でとあるブランチ状態のそのファイルの状態にチェックアウト

  3. for...inで上2つを繰り返し実行

これはhub(github/hub)に依存してます。
Macの人はbrewで入れれます。

brew intall hub

実例

以下で開けます。

hub browse -- pull/${PULL_NUMBER}

PULL_NUMBERは見たいプルリクのidです。
ただ多分プルリクのidは覚えてないことが多いのであまり使えないですが、GitHubはPULL_NUMBERがブランチ名の場合自動でidに変換してくれる仕様があります。つまり、こんな感じでいけます。

hub browse -- pull/${BRANCH_NAME}

よく使うものとして、今いるブランチのプルリクを開きたいと思うかもしれませんが、それはこうします。git rev-parse --abbrev-ref HEADは今いるブランチ名を取得しています。

hub browse -- pull/`git rev-parse --abbrev-ref HEAD`

bashエイリアス

こんな感じで登録すると便利か…も?

function openpull () {
  current_branch_name=`git rev-parse --abbrev-ref HEAD`
  hub browse -- pull/${1:-$current_branch_name}
}
alias openpull=openpull

openpull 
# 現在のブランチで開く
openpull foo
# fooブランチで開く

masterブランチでfooという Submodule は aaaaaa というコミットが最新です。そしてそこから、update-submoduleというブランチを切って Submodule 情報を更新して、 bbbbbb というコミットを最新にしました。
その後、git checkout masterで元ブランチに戻ると foo ディレクトリに差分ができています。

git status
# On branch master
# Your branch is up to date with 'origin/master'.
#
# Changes not staged for commit:
#   (use "git add ..." to update what will be committed)
#   (use "git checkout -- ..." to discard changes in working directory)
#         modified:   foo (new commits)

元ブランチに戻ったときの submodule の差分を解決する

これは以下のコマンドで直すことができます。 Submodule を最初期化する感じです。

git submodule update --init

JavaScript で飯食べたい歴約 5 年、 純( nju33 ) によるノートサイトです。

このサイトではドリンク代や奨学金返済の為、広告などを貼らせて頂いてますがご了承ください。

Change Log