Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

introduce git-pstash (public stash) #410

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions Commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
- [`git root`](#git-root)
- [`git delta`](#git-delta)
- [`git merge-repo`](#git-merge-repo)
- [`git pstash`](#git-pstash)

## git extras

Expand Down Expand Up @@ -853,3 +854,45 @@ $ git merge-repo [email protected]:tj/git-extras.git master .
```

The above merges a remote repo's `master` branch into the current repository's directory, not preserving history.

## git pstash

Similar to builtin `git stash` but keeps your stashes on remote as well.

```bash
$ git pstash
$ git pstash save
```

Any of the above creates new stash with "${USER}_${current_branch_name}_wip" name. Your working directory is left untouched.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps this should be wip/${USER}/${current_branch_name} to follow branch name convention.


```bash
$ git pstash save custom_name
```

The above customizes new stash's name.

```bash
$ git pstash apply stash_name
$ git pstash pop stash_name
```

Any of the above applies changes of given stash, but `pop` also drops the stash.

```bash
$ git pstash drop stash_name
```

The above drops given stash.

```bash
$ git pstash show stash_name
```

The above shows the changes recorded in given stash as a diff between the stashed state and its original parent.

```bash
$ git pstash list [search-substring]
```

The above fetches pstash updates from remote and lists available stashes.
78 changes: 78 additions & 0 deletions bin/git-pstash
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
#!/usr/bin/env bash

die()
{
echo "ERROR: $*"
exit 4
}
report_context()
{
echo "[pstash] branch: $branch, remote: $remote, ref: $ref_prefix/$ref"
}
set_ref()
{
ref=$(echo -n "$1" | tr ' \t' '_')
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you change echo -n to printf?

}
fetch_refs()
{
git fetch -p "$remote" "$ref_prefix/*:$ref_prefix/*" >/dev/null 2>&1 # TODO: what if not refreshed?
}

branch=$(git rev-parse --abbrev-ref HEAD)
test -n "$branch" || die "Cannot detect branch name."

remote=$(git config --get branch.${branch}.remote)
test -n "$remote" || die "Cannot detect ${branch} branch's remote. I expect you have remote tracking configured."

ref_prefix="refs/pstash"
ref=""

case "$1" in
save)
set_ref "$2"
test -z "$ref" && set_ref "${USER}_${branch}_wip"
report_context
hash=$(git stash create) || die "'git stash create' failed."
git push -f "$remote" "$hash:$ref_prefix/$ref"
# TODO: an option to reset working directory? to follow behaviour of 'git stash'
;;

apply)
set_ref "$2"
test -n "$ref" || die "Please, specify stash name to apply."
report_context
fetch_refs
# TODO: error if given stash not found?
git stash apply --index "$ref_prefix/$ref"
;;

drop)
set_ref "$2"
test -n "$ref" || die "Please, specify stash name."
report_context
fetch_refs
"$0" list | grep "$ref_prefix/$ref$" || die "Given stash name not found."
git push "$remote" ":$ref_prefix/$ref" && git update-ref -d "$ref_prefix/$ref"
;;

pop)
"$0" apply "$2" && "$0" drop "$2"
;;

show)
set_ref "$2"
test -n "$ref" || die "Please, specify stash name."
git diff "$ref_prefix/$ref^" "$ref_prefix/$ref"
;;

list)
fetch_refs
git show-ref | grep "$ref_prefix" | grep "$2"
# TODO: show datetime and sort order by?
;;

*)
"$0" save
;;
esac

4 changes: 4 additions & 0 deletions etc/bash_completion.sh
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,10 @@ _git_missing(){
__gitcomp "$(git for-each-ref --format='%(refname:short)')"
}

_git_pstash(){
__gitcomp "save apply drop pop show list"
}

_git_refactor(){
__git_extras_workflow "refactor"
}
Expand Down
5 changes: 4 additions & 1 deletion man/git-extras.1
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
.TH "GIT\-EXTRAS" "1" "June 2015" "" ""
.TH "GIT\-EXTRAS" "1" "July 2015" "" ""
.
.SH "NAME"
\fBgit\-extras\fR \- Awesome GIT utilities
Expand Down Expand Up @@ -129,6 +129,9 @@ Self update\.
\fBgit\-pr(1)\fR Checks out a pull request locally
.
.IP "\(bu" 4
\fBgit\-pstash(1)\fR Public stash
.
.IP "\(bu" 4
\fBgit\-rebase\-patch(1)\fR Rebases a patch
.
.IP "\(bu" 4
Expand Down
5 changes: 3 additions & 2 deletions man/git-extras.html

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions man/git-extras.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ git-extras(1) -- Awesome GIT utilities
- **git-merge-repo(1)** Merge two repo histories
- **git-missing(1)** Show commits missing from another branch
- **git-pr(1)** Checks out a pull request locally
- **git-pstash(1)** Public stash
- **git-rebase-patch(1)** Rebases a patch
- **git-refactor(1)** Create refactor branch
- **git-release(1)** Commit, tag and push changes to the repository
Expand Down
63 changes: 63 additions & 0 deletions man/git-pstash.1
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
.TH "GIT\-PSTASH" "1" "July 2015" "" ""
.
.SH "NAME"
\fBgit\-pstash\fR \- public stash
.
.SH "SYNOPSIS"
.
.IP "\(bu" 4
\fBgit\-pstash\fR [save [<stash\-name>]]
.
.IP "\(bu" 4
\fBgit\-pstash\fR apply <stash\-name>
.
.IP "\(bu" 4
\fBgit\-pstash\fR drop <stash\-name>
.
.IP "\(bu" 4
\fBgit\-pstash\fR pop <stash\-name>
.
.IP "\(bu" 4
\fBgit\-pstash\fR show <stash\-name>
.
.IP "\(bu" 4
\fBgit\-pstash\fR list [search\-substring]
.
.IP "" 0
.
.SH "DESCRIPTION"
Stashes your changes using built\-in \'git stash create\' and pushes it to remote\. In contrast to \'git stash\' it keeps your working directory untouched upon stashing\. Its stash namespace doesn\'t clash anyhow with built\-in \'git stash\', all references are kept under refs/pstash/\.
.
.SH "OPTIONS"
<stash\-name>
.
.P
Custom stash name\. It\'s set to ${USER}\fI${branch_name}\fRwip by default\.
.
.SH "EXAMPLES"
.
.nf

$ git pstash
$ git pstash save
$ git pstash save jack_master_wip
$ git pstash apply jack_master_wip
$ git pstash drop jack_master_wip
$ git pstash pop jack_master_wip
$ git pstash show jack_master_wip
$ git pstash list
$ git pstash list jack
.
.fi
.
.SH "AUTHOR"
Written by Igor Ostapenko <\fIigor\.ostapenko@gmail\.com\fR>
.
.SH "REPORTING BUGS"
<\fIhttps://github\.com/tj/git\-extras/issues\fR>
.
.SH "SEE ALSO"
<\fIhttps://github\.com/tj/git\-extras\fR>
135 changes: 135 additions & 0 deletions man/git-pstash.html

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading