Last active
August 1, 2024 01:25
-
-
Save mgaitan/d9a3523d79cd5f9fbfd626f646f0560b to your computer and use it in GitHub Desktop.
git smart switch : Like `git switch` but stashing uncommitted changes and recovering them when you are back.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
# -*- coding: utf-8 -*- | |
""" | |
Git smart switch | |
Like `git switch` but stashing uncommitted changes and recovering them when you are back. | |
# Install | |
Save this file somewhere in your PATH as `git-sw`, and add execution permission. | |
Git will recognize it as the "sw" subcommand. | |
# Example | |
Suppose you have a dirty branch like this | |
``` | |
$ git status -uno | |
On branch fix/cloud_ | |
Your branch is up to date with 'origin/fix/cloud_'. | |
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: shipping/shipping/domain/carriers/labeler.py | |
modified: shipping/tests/domain/carriers/test_labeler.py | |
``` | |
You can switch with git sw | |
``` | |
$ git sw master | |
Switched to branch 'master' | |
``` | |
The changes have been stashed | |
``` | |
$ git status -uno | |
On branch master | |
Your branch is behind 'origin/master' by 1 commit, and can be fast-forwarded. | |
(use "git pull" to update your local branch) | |
nothing to commit (use -u to show untracked files) | |
``` | |
Later you want to go back to the branch `fix/cloud_`. Just run git sw again | |
``` | |
$ git sw - | |
Switched to branch 'fix/cloud_' | |
``` | |
And your stashed changes will be there again | |
``` | |
$ git status -uno | |
On branch fix/cloud_ | |
Your branch is up to date with 'origin/fix/sendcloud_'. | |
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: shipping/shipping/domain/carriers/labeler.py | |
modified: shipping/tests/domain/carriers/test_labeler.py | |
``` | |
""" | |
import argparse | |
import re | |
import subprocess | |
parser = argparse.ArgumentParser(description="Smart switch") | |
parser.add_argument("branch", help="Switch to a specified branch.") | |
args = parser.parse_args() | |
current_branch = subprocess.check_output(["git", "branch", "--show-current"], text=True).strip() | |
# try to stash the current state setting a parseable message with the branch | |
subprocess.check_output(["git", "stash", "--message", f"[smart switch] {current_branch}"], text=True) | |
# switch | |
subprocess.check_output(["git", "switch", args.branch]) | |
# this is the same than args.branch but also expand references like "-" | |
target_branch = subprocess.check_output(["git", "branch", "--show-current"], text=True).strip() | |
# list stashes to find if there is something to pop | |
stashes_list = subprocess.check_output(["git", "stash", "list"], text=True) | |
stashes = {branch_name: stash_index for (stash_index, branch_name) in re.findall(r"stash@\{(\d+)\}\: .*: \[smart switch\] (.*)", stashes_list)} | |
stash_index = stashes.get(target_branch) | |
if stash_index is not None: | |
subprocess.check_output(["git", "stash", "pop", "--index", stash_index]) |
In line 82, the push
command is missing, so it gives error. The correct version is:
subprocess.check_output(["git", "stash", "push", "--message", f"[smart switch] {current_branch}"], text=True)
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
see also https://gist.github.com/mgaitan/ba1e4e252b90a7fd4a4eb9e1742e94fb