20 Commits

Author SHA1 Message Date
Ivan Malopinsky 7d0d33d32b Merge pull request #93 from imsky/main
Add support for main branch as root
2020-10-27 19:24:51 -04:00
Ivan Malopinsky b2fd270558 1.13.0 2020-10-27 19:23:55 -04:00
Ivan Malopinsky 3d7177e84c if only main branch exists, use that as root 2020-10-27 19:22:46 -04:00
Ivan Malopinsky 8bbe2a7d49 Merge pull request #92 from hrishabh23/ppwd
Change dir to repo root before making changes
2019-10-12 14:50:53 -04:00
Hrishabh 136a777d73 Change dir to repo root before making changes 2019-10-12 01:34:54 +05:30
Ivan Malopinsky 9dd178ded8 1.12.1 2019-06-23 20:07:35 -04:00
Ivan Malopinsky 6ad55433df use correct commit from log for root recovery 2019-05-27 15:54:48 -04:00
Ivan Malopinsky cf050df1f6 fix recovery logic, recover root before getting current commit 2019-05-27 15:39:44 -04:00
Ivan Malopinsky 074154e726 add root HEAD recovery function 2019-05-27 15:30:07 -04:00
Ivan Malopinsky 900e9120b5 update LICENSE years 2019-01-21 18:09:47 -05:00
Ivan Malopinsky 8b0bc89eb8 minor tweaks to get around groff treating leading . as a special character 2019-01-21 18:08:56 -05:00
Ivan Malopinsky 3825d93ff6 1.12.0 2019-01-21 17:43:51 -05:00
Ivan Malopinsky 08f63dbdd4 install man page 2019-01-21 17:43:16 -05:00
Ivan Malopinsky 9a768e9b48 add more spacing to man page sections 2019-01-21 17:25:51 -05:00
Ivan Malopinsky 83f2c7c80b add git-fresh man page
fix #82
2019-01-21 17:23:25 -05:00
Ivan Malopinsky 57cdc7c0fa add --help flag 2019-01-21 16:58:52 -05:00
Ivan Malopinsky 48429ea4df add flag to clear stashed changes
fix #88
2019-01-21 16:47:42 -05:00
Ivan Malopinsky 57f08a9758 print an error message along with the error line
fix #89
2019-01-21 16:41:31 -05:00
Ivan Malopinsky 23a3a64d90 Merge pull request #86 from hultberg/patch-1
Added archlinux package
2018-02-19 13:18:44 -05:00
Edvin Hultberg 5953344240 Added archlinux package 2018-02-19 10:19:40 +01:00
6 changed files with 233 additions and 60 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
MIT License
Copyright (c) 2017 Ivan Malopinsky
Copyright (c) 2017-2020 Ivan Malopinsky
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
+29 -22
View File
@@ -5,40 +5,46 @@ Keep your repo fresh with one command.
## Usage
```
Usage: git fresh [-fmrtRW] [-sl] [remote] [root]
By default, git-fresh will:
- update local root (master) to match remote root
- stash changes
- prune remote branches
SYNOPSIS
git-fresh [-fmrtRWS] [-sl] [remote] [root]
git-fresh will ignore any branches listed in a .freshignore file.
.freshignore should contain branch names you would like to ignore
on separate lines. The file can exist in the current Git repo
or in the home directory, i.e. ~/.freshignore.
DESCRIPTION
git-fresh helps keep your Git repo fresh.
-f: Delete stale local and remote branches
-m: Merge remote root into current branch
-r: Rebase current branch against remote root
-t: Remove local tags that do not exist on remote
-R: Reset local root to remote root
-W: Wipe workspace clean
By default, git-fresh will:
- update local root (master) to match remote root
- stash changes
- prune remote branches
-s: Apply stashed changes after run
-l: Only delete local stale branches
git-fresh will ignore any branches listed in a .freshignore file.
.freshignore should contain branch names you would like to ignore
on separate lines. The file can exist in the current Git repo
or in the home directory, i.e. ~/.freshignore.
-v: Print git-fresh version and exit
remote is origin by default. root is master by default.
remote: remote name, origin by default
root: root branch, master by default
OPTIONS
-f Delete stale local and remote branches
-m Merge remote root into current branch
-r Rebase current branch against remote root
-t Remove local tags that do not exist on remote
-R Reset local root to remote root
-W Wipe workspace clean
-S Clear all stash entries
-s Apply stashed changes after run
-l Only delete local stale branches
-v Print git-fresh version and exit
```
## Installation
### Manual on Linux or MacOSX
### Manual on Linux or macOS
1. Clone or download
2. `cd git-fresh`
3. `sudo ./install`
3. `sudo ./install.sh`
### Manual on Windows
@@ -49,6 +55,7 @@ This usually is `C:\Program Files\Git\usr\bin`.
* [Homebrew](http://brew.sh/): `brew install git-fresh`
* [bpkg](http://www.bpkg.io/): `bpkg install imsky/git-fresh`
* [AUR](https://aur.archlinux.org/): [git-fresh](https://aur.archlinux.org/packages/git-fresh/)
## License
+118 -36
View File
@@ -1,4 +1,5 @@
#!/usr/bin/env bash
# generate man page with: txt2man.sh -t git-fresh <(./git-fresh -?) > git-fresh.1
# git-fresh
# https://github.com/imsky/git-fresh
@@ -6,33 +7,48 @@
# MIT License
usage () {
cat << EOD
Usage: git fresh [-fmrtRW] [-sl] [remote] [root]
By default, git-fresh will:
- update local root (master) to match remote root
- stash changes
- prune remote branches
cat << EOT
NAME
git-fresh
git-fresh will ignore any branches listed in a .freshignore file.
.freshignore should contain branch names you would like to ignore
on separate lines. The file can exist in the current Git repo
or in the home directory, i.e. ~/.freshignore.
SYNOPSIS
git-fresh [-fmrtRWS] [-sl] [remote] [root]
-f: Delete stale local and remote branches
-m: Merge remote root into current branch
-r: Rebase current branch against remote root
-t: Remove local tags that do not exist on remote
-R: Reset local root to remote root
-W: Wipe workspace clean
DESCRIPTION
git-fresh helps keep your Git repo fresh.
-s: Apply stashed changes after run
-l: Only delete local stale branches
By default, git-fresh will:
- update local root (master) to match remote root
- stash changes
- prune remote branches
-v: Print git-fresh version and exit
git-fresh will ignore any branches listed in a .freshignore file.
freshignore should contain branch names you would like to ignore
on separate lines. The file can exist in the current Git repo
or in the home directory, i.e. ~/.freshignore.
remote: remote name, origin by default
root: root branch, master by default
EOD
remote is origin by default. root is master by default.
OPTIONS
-f Delete stale local and remote branches
-m Merge remote root into current branch
-r Rebase current branch against remote root
-t Remove local tags that do not exist on remote
-R Reset local root to remote root
-W Wipe workspace clean
-S Clear all stash entries
-s Apply stashed changes after run
-l Only delete local stale branches
-v Print git-fresh version and exit
BUGS
Issues are tracked on GitHub: https://github.com/imsky/git-fresh
AUTHOR
Ivan Malopinsky - http://imsky.co
EOT
exit 0
}
@@ -47,12 +63,17 @@ die () {
}
error () {
die "Error on line $1: $(head -n $1 $0 | tail -1)"
ERR=${ERR:-unknown}
die "Error on line $1: $ERR"
}
trap 'error $LINENO' ERR
while getopts ":fmrtslRWTv" opt; do
if [[ "$1" = '--help' ]]; then
usage
fi
while getopts ":fmrtslRWSTv" opt; do
case $opt in
f)
FORCE_DELETE_STALE=true
@@ -78,11 +99,14 @@ while getopts ":fmrtslRWTv" opt; do
W)
WIPE_WORKSPACE=true
;;
S)
CLEAR_STASH=true
;;
T)
TEST=true
;;
v)
VERSION=1.11.0
VERSION=1.12.1
;;
*)
usage
@@ -132,20 +156,48 @@ if [[ -z "$INSIDE_GIT_REPO" ]]; then
fi
# Are we in a non-empty git repository?
ERR="could not get top-level-directory"
TOP_LEVEL_DIRECTORY=$(git rev-parse --show-toplevel)
REMOTE=${1:-origin}
ROOT=${2:-master}
if [[ $(ls -1 "$TOP_LEVEL_DIRECTORY/.git/refs/heads" | wc -l | xargs) -eq "0" ]]; then
if git rev-parse --verify "$ROOT"; then
git rev-parse "$ROOT" > "$TOP_LEVEL_DIRECTORY/.git/refs/heads/$ROOT"
else
(git fsck --lost-found &> /dev/null; git checkout "$ROOT") || die "No HEAD ref available"
fi
ROOT_GUESS=master
if [[ -n $(git show-ref refs/heads/main) && -z $(git show-ref refs/heads/master) ]]; then
ROOT_GUESS=main
fi
ROOT=${2:-$ROOT_GUESS}
# Recover the root HEAD if it is missing or corrupt (e.g. master head reads "master")
recover_root () {
ROOT_HEAD_FILE="$TOP_LEVEL_DIRECTORY/.git/refs/heads/$ROOT"
if [[ -e "$ROOT_HEAD_FILE" ]]; then
if [[ $(cat "$ROOT_HEAD_FILE") = $(echo $ROOT) ]]; then
CORRUPT_ROOT_HEAD=true
fi
else
MISSING_ROOT_HEAD=true
fi
if [[ "$CORRUPT_ROOT_HEAD" = "true" || "$MISSING_ROOT_HEAD" = "true" ]]; then
ERR="failed to recover $ROOT HEAD"
RECOVERED_ROOT_HEAD=$(cat "$TOP_LEVEL_DIRECTORY/.git/logs/refs/heads/$ROOT" | tail -n1 | cut -d' ' -f2)
echo "$RECOVERED_ROOT_HEAD" > "$ROOT_HEAD_FILE"
say "Recovered $ROOT HEAD, set to $RECOVERED_ROOT_HEAD"
CORRUPT_ROOT_HEAD=false
MISSING_ROOT_HEAD=false
fi
}
recover_root
LAST_WORKING_DIRECTORY="$(pwd)"
cd "$TOP_LEVEL_DIRECTORY"
ERR="could not get current commit"
CURRENT=$(git rev-parse --abbrev-ref HEAD)
ERR=""
if [[ $(git remote -v | wc -l) -gt "0" ]]; then
REMOTES=true
@@ -165,18 +217,18 @@ if [[ -f $FRESH_IGNORE ]]; then
fi
fi
STASH_STAMP=git-fresh-$(date +%s)
# Stash changed files
if ! git diff-files --quiet; then
ERR="could not stash changes"
git stash save $STASH_STAMP
fi
if [[ $REMOTES = true ]]; then
# Update remotes and prune stale remotes
ERR="could not update and prune remotes"
git remote prune $REMOTE
git remote update $REMOTE
git remote prune $REMOTE
@@ -185,28 +237,32 @@ fi
# If we are not already on root branch, switch to root branch (master)
if [[ "$ROOT" != "$CURRENT" ]]; then
ERR="could not check out $ROOT branch"
git checkout $ROOT > /dev/null 2>&1
fi
# Wipe workspace?
if [[ $WIPE_WORKSPACE = true ]]; then
ERR="could not wipe workspace"
git clean -dfx
fi
if [[ $REMOTES = true ]]; then
# Reset root?
if [[ $RESET_ROOT = true ]]; then
ERR="could not reset root"
git reset --hard $REMOTE/$ROOT
fi
ERR="could not perform fast forward merge"
git pull --quiet --ff-only $REMOTE $ROOT || say "Fast forward merge failed on $ROOT. You can reset local $ROOT by running git fresh -R."
fi
# Compute stale branches
ERR="could not determine stale branches"
SMART_STALE=$(git branch -a --merged | tr -d "\* " | grep -Ev ">|$ROOT" | cat)
LOCAL_STALE=$(grep -Ev "^remotes/" <<< "$SMART_STALE" | cat)
@@ -225,6 +281,7 @@ if [[ ! -z "${SMART_STALE// }" ]]; then
fi
fi
if [[ "$FORCE_DELETE_STALE" = true ]]; then
ERR="could not delete stale local branches: $LOCAL_STALE"
echo -n $LOCAL_STALE | tr " " "\0" | xargs -0 git branch -d 2> /dev/null
else
if [[ $STALE_BRANCHES = true ]]; then
@@ -243,6 +300,7 @@ if [[ ! -z "${SMART_STALE// }" ]]; then
fi
if [[ "$FORCE_DELETE_STALE" = true ]]; then
if [[ "$DELETE_ONLY_LOCAL" != true ]]; then
ERR="could not delete stale remote branches: $REMOTE_STALE"
echo -n $REMOTE_STALE | tr " " "\0" | xargs -0 git push $REMOTE --delete
fi
else
@@ -267,7 +325,9 @@ fi
if [[ ! -z $(git rev-parse --verify --quiet "$CURRENT") ]]; then
if [[ "$ROOT" != "$CURRENT" ]]; then
ERR="could not check out $CURRENT branch"
git checkout $CURRENT
recover_root
fi
if [ "$REBASE" = true ] && [ "$MERGE" = true ]; then
@@ -275,10 +335,12 @@ if [[ ! -z $(git rev-parse --verify --quiet "$CURRENT") ]]; then
else
if [[ "$REMOTES" = true ]]; then
if [[ "$REBASE" = true ]]; then
ERR="could not rebase against $ROOT branch"
git rebase $ROOT
fi
if [[ "$MERGE" = true ]]; then
ERR="could not merge $ROOT branch"
git merge --no-edit $ROOT
fi
fi
@@ -290,6 +352,7 @@ fi
# Remove local tags that are missing on the remote
if [[ "$TAGS" = true ]]; then
ERR="could not get remote tags"
REMOTE_TAGS=$(git ls-remote --tags $REMOTE | cut -f 2)
LOCAL_TAGS=$(git show-ref --tags | cut -d' ' -f 2)
@@ -305,13 +368,32 @@ fi
if [[ ! -z $(git stash list | grep $STASH_STAMP | cat) ]]; then
if [[ "$APPLY_STASH" = true ]]; then
ERR="could not apply stashed changes"
git stash pop
else
say "Stashed changes present, apply with: git stash pop"
fi
fi
# Clear stashed changes
if [[ "$CLEAR_STASH" = true ]]; then
ERR="could not clear stashed changes"
git stash clear
fi
if ! git gc --auto --force; then
ERR="git prune failed"
git prune
rm -rf "$TOP_LEVEL_DIRECTORY/.git/gc.log"
fi
if [[ -d "$LAST_WORKING_DIRECTORY" ]]; then
cd "$LAST_WORKING_DIRECTORY"
else
say "Previous working directory does not exist on the branch $ROOT"
fi
recover_root
ERR=""
+73
View File
@@ -0,0 +1,73 @@
." Text automatically generated by txt2man
.TH git-fresh "January 21, 2019" "" ""
.SH NAME
\fBgit-fresh
\fB
.SH SYNOPSIS
.nf
.fam C
\fBgit-fresh\fP [\fB-fmrtRWS\fP] [\fB-sl\fP] [\fIremote\fP] [\fIroot\fP]
.fam T
.fi
.SH DESCRIPTION
\fBgit-fresh\fP helps keep your Git repo fresh.
.PP
By default, \fBgit-fresh\fP will:
.IP \(hy 3
update local \fIroot\fP (master) to match \fIremote\fP \fIroot\fP
.IP \(hy 3
stash changes
.IP \(hy 3
prune \fIremote\fP branches
.PP
\fBgit-fresh\fP will ignore any branches listed in a .freshignore file.
\ .freshignore should contain branch names you would like to ignore
on separate lines. The file can exist in the current Git repo
or in the home directory, i.e. ~/.freshignore.
.PP
\fIremote\fP is origin by default. \fIroot\fP is master by default.
.SH OPTIONS
.TP
.B
\fB-f\fP
Delete stale local and \fIremote\fP branches
.TP
.B
\fB-m\fP
Merge \fIremote\fP \fIroot\fP into current branch
.TP
.B
\fB-r\fP
Rebase current branch against \fIremote\fP \fIroot\fP
.TP
.B
\fB-t\fP
Remove local tags that do not exist on \fIremote\fP
.TP
.B
\fB-R\fP
Reset local \fIroot\fP to \fIremote\fP \fIroot\fP
.TP
.B
\fB-W\fP
Wipe workspace clean
.TP
.B
\fB-S\fP
Clear all stash entries
.TP
.B
\fB-s\fP
Apply stashed changes after run
.TP
.B
\fB-l\fP
Only delete local stale branches
.TP
.B
\fB-v\fP
Print \fBgit-fresh\fP version and exit
.SH BUGS
Issues are tracked on GitHub: https://github.com/imsky/\fBgit-fresh\fP
.SH AUTHOR
Ivan Malopinsky - http://imsky.co
+11
View File
@@ -3,3 +3,14 @@ INSTALL_DIR=${1:-/usr/local/bin}
mkdir -p $INSTALL_DIR
cp git-fresh $INSTALL_DIR && ([ -e $INSTALL_DIR/git-fresh ] && echo git-fresh installed in $INSTALL_DIR)
if [[ -e /usr/local/man ]]; then
MAN_DIR=/usr/local/man
elif [[ -e /usr/local/share/man ]]; then
MAN_DIR=/usr/local/share/man
fi
if [[ ! -z "$MAN_DIR" ]]; then
mkdir -p "$MAN_DIR/man1"
cp git-fresh.1 "$MAN_DIR/man1/" 2> /dev/null || echo Failed to install git-fresh man page
fi
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "git-fresh",
"version": "1.11.0",
"version": "1.13.0",
"description": "Utility to keep Git repositories fresh",
"global": true,
"repo": "imsky/git-fresh",