Git でやってしまった!そんなときに変更を取り消す便利なツール “git-branchless”
はじめに
Git で誤って git reset
、 git rebase
をしてしまって冷や汗が出たことがある方は少なくないはずです。
僕も何度自分のローカルブランチでやってしまったことか。
焦りながらも git reflog
で最後の変更を見つけ出し、なんとかもとに戻せた!
という場合もあれば、
うまく戻せずに結局最初から開発やり直し…
となったこともあります。
git reflog
の操作が難しいですよね。
変更がもっとかんたんにもとに戻せたら、と常々思っていましたが、そんな問題にぴったりのツールを見つけました。
検証環境
$ uname -moi
x86_64 MacBookPro16,1 Darwin
$ zsh --version | head -n 1
zsh 5.8 (x86_64-apple-darwin19.6.0)
$ git version
git version 2.32.0
git-branchless
見つけたのは arxanas/git-branchless というツールになります。
git-branchless はツールのセットになります。
コミット履歴を 視覚化 、 ナビゲーション 、 操作の支援 、 修復 するのを手助けしてくれます。
"Google" や "Facebook" といった大企業で利用されている branchless Mercurial worlflows と呼ばれる開発フロー(?)に基づいているそうです。
インストール
Rust がインストールされていることが前提となっているようです。
$ brew install rust
Rust をインストールすると、Rust のビルド、パッケージマネージャーである cargo
というコマンドが使えるうようになります。
cargo
コマンドを使って git-branchless
をインストールします。
$ cargo install git-branchless
パスを通しておきます。
$ export PATH="$HOME/.cargo/bin:$PATH"
git
のサブコマンドが利用できるようになっているか確認してみます。
$ git branchless help
git-branchless 0.3.3
Waleed Khan <me@waleedkhan.name>
Branchless workflow for Git.
See the documentation at https://github.com/arxanas/git-branchless/wiki.
...
利用できそうです。
修正機能
そんな中でも一番使いそうな便利な機能が 修正機能 です。
どんな機能か使いながら理解してみます。
作業用 Git ワークスペースを作成
検証のために作業用 Git ワークスペースを作成します。
$ mkdir work
$ cd work
$ git init
Initialized empty Git repository in /private/tmp/work20210701_161735/work/.git/
ローカルの Git ワークスペースに git-branchless
の初期化設定を行う
Git ワークスペースに対して、 git branchless init
コマンドで初期化を行います。
これをして初めて git branchless
が使えるようになるようです。
作ったばかりのローカルリポジトリの場合は、「どのブランチをメインブランチにしますか?」と聞かれます。
今回は main
ブランチを指定しました。
$ git branchless init
Your main branch name could not be auto-detected!
Examples of a main branch: master, main, trunk, etc.
See https://github.com/arxanas/git-branchless/wiki/Concepts#main-branch
Enter the name of your main branch: main
Setting config (non-global): branchless.core.mainBranch = main
Setting config (non-global): advice.detachedHead = false
Installing hook: post-commit
Installing hook: post-rewrite
Installing hook: post-checkout
Installing hook: pre-auto-gc
Installing hook: reference-transaction
Installing alias (non-global): git smartlog -> git branchless smartlog
Installing alias (non-global): git sl -> git branchless smartlog
Installing alias (non-global): git hide -> git branchless hide
Installing alias (non-global): git unhide -> git branchless unhide
Installing alias (non-global): git prev -> git branchless prev
Installing alias (non-global): git next -> git branchless next
Installing alias (non-global): git restack -> git branchless restack
Installing alias (non-global): git undo -> git branchless undo
Installing alias (non-global): git move -> git branchless move
Successfully installed git-branchless.
To uninstall, run: git branchless init --uninstall
コミットを重ねた後に取り消し( undo
)してみる
それではコミットを重ねた後に取り消しして見ます。
まずは適当なコミットを何度か行ってみます。
# 1. fooというファイルを作成 ( "Hello, world!" と書かれている )
echo 'Hello, world!' >foo
# 2. git commmit
git add foo
git commit -m "first commit."
# 3. 内容を書き換える
echo 'Goodby, world!' >foo
# 4. git commmit (前のコミットに強制的に追加する)
git add foo
git commit --amend -m "Amend foo bad"
実はこの git commit --amend
、間違いだったことに気が付きました。
がときすでに遅し。
$ git log
commit 8eb37409d550bf4e7b5f039fd690b2d2fd95fb60 (HEAD -> main, refs/branchless/8eb37409d550bf4e7b5f039fd690b2d2fd95fb60)
Author: genzouw <genzouw@gmail.com>
Date: Thu Jul 1 16:33:16 2021 +0900
Amend foo bad
# git sl でもcommit historyが閲覧できる
$ git sl
◆ 8eb37409 34m (main) Amend foo bad
コミットがくっついてしまいましたとさ。。。
しかし落ち着きましょう。
こんなときには git undo
を実行します。
$ git undo -i
すると以下のような画面になります。
n / p キーを押すと、変更履歴が表示されますので、戻したい履歴が表示されたら ENTER キーを押します。
完全に最初のコミットまで戻すこともできますし、
# コミット履歴
$ git log
commit 29f637f8c89e3126271a8a67d90785987d6583f0 (HEAD, main)
Author: genzouw <genzouw@gmail.com>
Date: Thu Jul 1 16:33:16 2021 +0900
first commit.
$ git sl
◆ 29f637f8 46m (main) first commit.
# ファイルの中身を確認 (戻っている)
$ cat foo
Hello, world!
2 つ目のコミットを残したままにすることもできます。(修正を微調整する場合はこちらですね。)
# コミット履歴 (まだ戻っていない)
$ git log
commit 8eb37409d550bf4e7b5f039fd690b2d2fd95fb60 (HEAD, refs/branchless/8eb37409d550bf4e7b5f039fd690b2d2fd95fb60)
Author: genzouw <genzouw@gmail.com>
Date: Thu Jul 1 16:33:16 2021 +0900
Amend foo bad
$ git sl
◇ 29f637f8 48m (main) first commit.
⦻ 8eb37409 48m (rewritten as 29f637f8) Amend foo bad
# ファイルの中身を確認 (戻っていない)
$ cat foo
Goodby, world!
# コミット履歴を戻す
$ git reset --soft main
branchless: processing 1 update to a branch/ref
# ステージング状態まで戻せた!
$ git diff --cached
diff --git foo foo
index af5626b..c6e4c2b 100644
--- foo
+++ foo
@@ -1 +1 @@
-Hello, world!
+Goodby, world!
ひとこと
もう少し使ってみて、発見があればエントリを更新していきたいと思います。
ディスカッション
コメント一覧
まだ、コメントがありません