Gitの自分用メモ:トラッキングせずにブランチを作りたい。カレントブランチのポインタを移動させたい。

気分転換といえばGit。ということでGitを触ってた。

僕がGitでよくやる操作があって、それは複数のコマンドを叩いてるんだけど、簡単にできるものが用意されてるだろうなぁとずっと思っていて、やっと調べることにした。自分用メモ。

トラッキングせずにブランチを作りたい

リモートブランチをトラッキングするのは、あまり好きではないので、切り離してブランチを作りたくて、こうしてた↓

  1. git switch -d origin/<リモートブランチ名> でDETACHED HEADの状態にする
  2. git switch -c <ローカルブランチ名> でカレントコミットから作成するとリモートブランチをトラッキングしない

手元に fastify のリポジトリがあったので、このリポジトリで試すことにする。

❯ git switch -d origin/next
Previous HEAD position was 4415c2fb chore: add github sponsor (#5293)
HEAD is now at c30992b5 feat: align fastify.hasRoute to fmw.hasRoute (#5102)

❯ git switch -c sample
Switched to a new branch 'sample'

❯ git branch -vv
  main   4415c2fb [origin/main] chore: add github sponsor (#5293)
* sample c30992b5 feat: align fastify.hasRoute to fmw.hasRoute (#5102)

こんなふうにして、トラッキングしないローカルブランチを作ってた。

もしくはこうしてた。

  1. git switch -c <ローカルブランチ名> -d origin/<リモートブランチ名> でトラッキングした状態になる
  2. git branch --unset-upstream でトラッキングを外す

さっきのブランチを消しておく(これ以降もやってるけどもう書かない)

❯ git switch main && git branch -D sample
Switched to branch 'main'
Your branch is up to date with 'origin/main'.
Deleted branch sample (was c30992b5).

リモートブランチからローカルブランチを作る。

❯ git switch -c sample origin/next
branch 'sample' set up to track 'origin/next'.
Switched to a new branch 'sample'

❯ git branch -vv
  main   4415c2fb [origin/main] chore: add github sponsor (#5293)
* sample c30992b5 [origin/next] feat: align fastify.hasRoute to fmw.hasRoute (#5102)

↑この時点では origin/next をトラッキングしてる。

❯ git branch --unset-upstream

❯ git branch -vv
  main   4415c2fb [origin/main] chore: add github sponsor (#5293)
* sample c30992b5 feat: align fastify.hasRoute to fmw.hasRoute (#5102)

これでトラッキングが外れた。

調べた

--no-track オプションがあった。もっとはやくに調べるべきだったよね。それはそう。

https://git-scm.com/docs/git-switch#Documentation/git-switch.txt---no-track

--no-track を使ってみよう。

❯ git switch --no-track -c sample origin/next
Switched to a new branch 'sample'

❯ git branch -vv
  main   4415c2fb [origin/main] chore: add github sponsor (#5293)
* sample c30992b5 feat: align fastify.hasRoute to fmw.hasRoute (#5102)

便利!エイリアスを登録した。いまさらだけど switch 自体も登録した。

❯ git config --global alias.sw switch

❯ git config --global alias.swn 'switch --no-track'

❯ git config --list | grep 'alias\.sw'
alias.sw=switch
alias.swn=switch --no-track

こんな感じで使える。便利!

❯ git swn -c sample origin/next
Switched to a new branch 'sample'

❯ git branch -vv
  main   4415c2fb [origin/main] chore: add github sponsor (#5293)
* sample c30992b5 feat: align fastify.hasRoute to fmw.hasRoute (#5102)

よし。これでいこ。

ついでに git branch のエイリアスも作っといた。スイッチせずにブランチを作りたいとき用。

❯ git config --global alias.br branch

❯ git config --global alias.brn 'branch --no-track'

❯ git config --list | grep 'alias\.br'
alias.br=branch
alias.brn=branch --no-track

よし。

と書きながら思ったんだけど、ブランチを指定するんじゃなくてコミットを指定したら最初からトラッキングされないね。

❯ git switch -c sample c30992b5
Switched to a new branch 'sample'

❯ git branch -vv
  main   4415c2fb [origin/main] chore: add github sponsor (#5293)
* sample c30992b5 feat: align fastify.hasRoute to fmw.hasRoute (#5102)

まぁ、ブランチからできたら便利なので、--no-track 使っていこう。

カレントブランチのポインタを移動させたい

カレントブランチの名前をそのままにして、別のコミットを指すように移動したいなってときも結構あって、こうしてた。

  1. git switch -d <移動先のコミット> で移動先のコミットにDETACHED HEAD状態で移動する
  2. git branch -D <ローカルブランチ> でローカルブランチを削除
  3. git switch -c <ローカルブランチ> でローカルブランチを作成
# 準備。このsampleブランチが別のコミットを指すようにしたい
❯ git swn -c sample origin/next
Switched to a new branch 'sample'

# 移動先のコミットに移動(コミットハッシュは適当に選んだ)
❯ git sw -d 79042e60
HEAD is now at 79042e60 fix: ensure `onListen` hooks are called when they should be (#5273)

# ローカルブランチを削除
❯ git br -D sample
Deleted branch sample (was c30992b5).

# ローカルブランチを作成
❯ git sw -c sample
Switched to a new branch 'sample'

❯ git br -vv
  main   4415c2fb [origin/main] chore: add github sponsor (#5293)
* sample 79042e60 fix: ensure `onListen` hooks are called when they should be (#5273)

どうしてこんな面倒なことを、これまで調べようとしなかったのか。

調べた

git reset --hard でできるのかー。

❯ git swn -c sample origin/next
Switched to a new branch 'sample'

❯ git reset --hard 79042e60
HEAD is now at 79042e60 fix: ensure `onListen` hooks are called when they should be (#5273)

❯ git br -vv
  main   4415c2fb [origin/main] chore: add github sponsor (#5293)
* sample 79042e60 fix: ensure `onListen` hooks are called when they should be (#5273)

うーん。でも、git reset --hard って作業がふっとぶ可能性があって苦手なんだよなぁ。まだコミットしてない変更があったら止まってほしいな・・・。と思ってたら、git switch-C オプションがあった。force createかー。見てみよっと。

https://git-scm.com/docs/git-switch#Documentation/git-switch.txt--Cltnew-branchgt

❯ git swn -c sample origin/next
Switched to a new branch 'sample'

❯ git sw -C sample 79042e60
Reset branch 'sample'

❯ git br -vv
  main   4415c2fb [origin/main] chore: add github sponsor (#5293)
* sample 79042e60 fix: ensure `onListen` hooks are called when they should be (#5273)

ふむふむ。いい動き。カレントブランチでも問題なく移動できてる。

で、肝心の、コミットしていない変更がある場合はどうなるんだろう?

❯ git swn -c sample origin/next
Switched to a new branch 'sample'echo "sample" >> README.md

❯ git status
On branch sample
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
        modified:   README.md

no changes added to commit (use "git add" and/or "git commit -a")

これで README.md に変更がある状態になった。移動してみよう。

❯ git sw -C sample 79042e60
error: Your local changes to the following files would be overwritten by checkout:
        README.md
Please commit your changes or stash them before you switch branches.
Aborting

わー。止まってくれたー。やったー!

まとめ

自分の環境だと、こうなった。

  • トラッキングせずにブランチを作りたい → git swn -c <ローカルブランチ名> <リモートブランチ名>
  • カレントブランチのポインタを移動させたい → git sw -C <ローカルブランチ名> <移動先>

結論 → git switch はいいぞ。