はじめに
Git で誤って git reset 、 git rebase をしてしまって冷や汗が出たことがある方は少なくないはずです。
僕も何度自分のローカルブランチでやってしまったことか。
焦りながらも git reflog で最後の変更を見つけ出し、なんとかもとに戻せた!
という場合もあれば、
うまく戻せずに結局最初から開発やり直し…
となったこともあります。
git reflog の操作が難しいですよね。
変更がもっとかんたんにもとに戻せたら、と常々思っていましたが、そんな問題にぴったりのツールを見つけました。
検証環境
1
2
3
4
5
6
7
8
| $ 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 がインストールされていることが前提となっているようです。
Rust をインストールすると、Rust のビルド、パッケージマネージャーである cargo というコマンドが使えるうようになります。
cargo コマンドを使って git-branchless をインストールします。
1
| $ cargo install git-branchless
|
パスを通しておきます。
1
| $ export PATH="$HOME/.cargo/bin:$PATH"
|
gitのサブコマンドが利用できるようになっているか確認してみます。
1
2
3
4
5
6
7
| $ 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 ワークスペースを作成します。
1
2
3
4
5
6
| $ 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 ブランチを指定しました。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
| $ 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
2
3
4
5
6
7
8
9
10
11
12
13
| # 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 、間違いだったことに気が付きました。
がときすでに遅し。
1
2
3
4
5
6
7
8
9
10
| $ 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 を実行します。
すると以下のような画面になります。

n / p キーを押すと、変更履歴が表示されますので、戻したい履歴が表示されたら ENTER キーを押します。
完全に最初のコミットまで戻すこともできますし、
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| # コミット履歴
$ 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 つ目のコミットを残したままにすることもできます。(修正を微調整する場合はこちらですね。)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
| # コミット履歴 (まだ戻っていない)
$ 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!
|
ひとこと
もう少し使ってみて、発見があればエントリを更新していきたいと思います。