git stashの有効範囲を調べる
以前の記事でも記載した様にGitは、fileを6つの状態で扱う。
programmingforever.hatenablog.com
そこで、その内ローカル側の5つの状態のfileをgit stash
コマンドでどの様に退避するのかをまとめた。但しcommitはstashの対象にならないため実際は以下の2から5までの状態に置いた4つのfileの退避を確認する。
各shell scriptの状態
説明のために5つのfileをそれぞれ下記の状態にして動作を追う。
- a.sh:fileをcommitした状態
- b.sh:fileを変更してstagingした状態
- c.sh:fileを変更してstagingしていない状態
- d.sh:fileをGitがまだ追跡していない状態(新規file等)
- e.sh:fileをGitが無視する状態(.gitignoreで指定したfile)
コマンドで退避前の各fileの状態を確認
$ ls a.sh b.sh c.sh d.sh e.sh # - 各fileが見える $ git status On branch main Changes to be committed: (use "git restore --staged <file>..." to unstage) modified: b.sh # - b.shはstaging中(変更あり) 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: c.sh # - c.shは変更あり Untracked files: (use "git add <file>..." to include in what will be committed) d.sh # - d.shはGit追跡対象外、e.shは無視なので見えない $
図で退避される範囲を確認
git stash
Gitの追跡対象かつ変更したfile及びfolderを作業ディレクトリとstagingから退避し、作業ディレクトリとstagingをcommt直後に戻す。
git stash pop
で退避を戻すとstaging状態が解除されている。またstagingしたfileを追加修正してstagingしていない場合、stagingしたfileは消失して追加修正したfileが残る。
- ー
- 退避する(commit直後のstaging状態に戻る)
- 退避する(commit直後の作業ディレクトリ状態に戻る)
- 退避しない
- 退避しない
$ git stash # - 退避を実行 Saved working directory and index state WIP on main: 80afbdd test1 $ ls a.sh b.sh c.sh d.sh e.sh # - b.sh, c.shの内容は変更前に戻っている $ git status On branch main Untracked files: (use "git add <file>..." to include in what will be committed) d.sh # - staging中のb.sh、変更&staging前のc.shが消えた nothing added to commit but untracked files present (use "git add" to track) $ git stash show # - b.shとc.shが退避されているのが見える b.sh | 2 +- c.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) $ git stash pop # - 退避を元に戻すと・・ On branch main 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: b.sh # - stagingが解除されている点に注意 modified: c.sh Untracked files: (use "git add <file>..." to include in what will be committed) d.sh no changes added to commit (use "git add" and/or "git commit -a") Dropped refs/stash@{0} (ec403a9850501332a6bbc52a694c5473c97ba435) $ git add b.sh # - 必要に応じてstagingし直す $
git stash -k
-kオプションを付けると、Gitの追跡対象かつ変更したfile及びfolderを作業ディレクトリとstagingから退避し、作業ディレクトリはcommit直後に戻すが、staging状態は現状を維持する。
stagingしたfileを追加修正してstagingしていない場合は、stagingした内容と追加修正した内容が、git stash pop
で退避を戻す際にマージされるので対象fileを編集してconflictを解決する。
- ー
- 退避する(staging状態を維持する)
- 退避する(commit直後の作業ディレクトリ状態に戻る)
- 退避しない
- 退避しない
$ git stash -k # - -kオプションを付けて実行 Saved working directory and index state WIP on main: 80afbdd test1 $ git status On branch main Changes to be committed: (use "git restore --staged <file>..." to unstage) modified: b.sh # - stagingのb.shが残っている Untracked files: (use "git add <file>..." to include in what will be committed) d.sh # - 変更&staging前のc.shが隠され、追跡外のd.shが見える $ git stash show # - b.shとc.shが退避されているのが見える b.sh | 2 +- c.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) $ git stash pop # - 退避を元に戻すとstash前と同じ状態 On branch main Changes to be committed: (use "git restore --staged <file>..." to unstage) modified: b.sh 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: c.sh Untracked files: (use "git add <file>..." to include in what will be committed) d.sh Dropped refs/stash@{0} (c976e74a49d3960940bd367e1da312d030cf75f9) $
git stash -u
-uオプションを付けると、Gitの追跡対象かつ変更したfile及びfolderを作業ディレクトリとstagingから退避し、作業ディレクトリとstagingをcommt直後に戻す動作に加えて、
作業ディレクトリ内のGit追跡対象外のfile及びfolderも、作業ディレクトリとstaging内から退避して、popするまで作業ディレクトリから消失させる。但し.gitignoreで指定したfileは退避しない。空のfolderは削除されて戻らない。
- ー
- 退避する(commit直後のstaging状態に戻る)
- 退避する(commit直後の作業ディレクトリ状態に戻る)
- 退避する
- 退避しない
$ git stash -u # - -uオプション付きで退避を実行 Saved working directory and index state WIP on main: 80afbdd test1 $ ls a.sh b.sh c.sh e.sh # - Git追跡対象外fileのd.shが消えた $ git status On branch main nothing to commit, working tree clean # - 何も変更がないと表示される $ git stash pop # - 退避を戻すと・・・ On branch main 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: b.sh # - stagingは外される modified: c.sh Untracked files: (use "git add <file>..." to include in what will be committed) d.sh no changes added to commit (use "git add" and/or "git commit -a") Dropped refs/stash@{0} (11ee1ab69090b3360d2f19bf97b9a646f575fc15) $ ls a.sh b.sh c.sh d.sh e.sh # - 消えたd.shが復活 $ git add b.sh # - 必要に応じてstagingし直す $
git stash -a
-aオプションを付けると、Gitの追跡対象かつ変更したfile及びfolderを作業ディレクトリとstagingから退避し、作業ディレクトリとstagingをcommt直後に戻す動作に加えて、
作業ディレクトリ内のGit追跡対象外やGitに無視する様に指定したfile及びfolderも、作業ディレクトリとstaging内から退避して、popするまで作業ディレクトリから消失させる。空のfolderは削除されて戻らない。
- ー
- 退避する(commit直後のstaging状態に戻る)
- 退避する(commit直後の作業ディレクトリ状態に戻る)
- 退避する
- 退避する
$ git stash -a # - -aオプション付きで退避を実行 Saved working directory and index state WIP on main: 80afbdd test1 $ ls a.sh b.sh c.sh # - Git追跡対象外のd.shと無視指定のe.shが消えた $ git status On branch main nothing to commit, working tree clean # - 何も変更がないと表示される $ git stash pop # - 退避を戻すと・・・ On branch main 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: b.sh # - stagingは外される modified: c.sh Untracked files: (use "git add <file>..." to include in what will be committed) d.sh no changes added to commit (use "git add" and/or "git commit -a") Dropped refs/stash@{0} (11ee1ab69090b3360d2f19bf97b9a646f575fc15) $ ls a.sh b.sh c.sh d.sh e.sh # - 消えたd.sh, e.shが復活 $ git add b.sh # - 必要に応じてstagingし直す $
git stash -- files
git stash -- files
で指定fileだけを退避出来る。
git stash -p
git stash -p
でハンク単位で退避出来る。