Skip to content

Commit

Permalink
Remove useless branches in a repository
Browse files Browse the repository at this point in the history
The purpose of `clear-local` command is to remove branches that have
unexisting upstreams. And it starts asking for deleting branches if they
aren't merged. But this behavior is overengineering and, usually, all
these branches have to be removed.

As the solution, the `prune-repository` command is introduced which
makes safe automatic cleanup of all useless branches. Also, it doesn't
try to save your working state by using pipes. This is because that if
`prune-repository` is executed, then the repository should not have
uncommitted changes, otherwise, it will fail.
  • Loading branch information
extsoft committed Nov 23, 2019
1 parent c75b7ee commit 47ea024
Show file tree
Hide file tree
Showing 7 changed files with 139 additions and 142 deletions.
52 changes: 28 additions & 24 deletions docs/commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ There are commands used in various situations such as
clone-repository Clones a repository and configures it.
init-repository Initializes a new repository and configures it.
acquire-repository Configures current repository.
clear-local Removes obsolete local branches.
prune-repository Removes useless local branches.

manage a personal work
start-work Creates a new branch.
Expand Down Expand Up @@ -118,29 +118,6 @@ git diff --cached --check
git commit --amend
```

# `clear-local`

```bash
usage: git elegant clear-local
```

Identifies local branches for which remote branches were removed. Then, it
removes them by invoking `git branch -d`. If there are unmerged branches, you
have to choose either batch or one-by-one deletion procedure using
`git branch -D`.

Prior to the execution, a current state is saved (a branch with modifications).
After the successful accepting a work, the state will be restored. In the case
of a failure, you need to go to the desired branch and apply a stash if needed.

Approximate commands flow is
```bash
==>> git elegant clear-local
git branch -d task-24
git branch -d 2349
git branch -D task-1
```

# `clone-repository`

```bash
Expand Down Expand Up @@ -243,6 +220,33 @@ Approximate commands flow is
git rebase --interactive @~5
```

# `prune-repository`

```bash
usage: git elegant prune-repository
```

Identifies useless branches within the current repository and removes them. A
branch is useless if it either has configured an unavailable upstream branch (1)
or does not have new commits comparing to `master` branch (2).

1 - Usually, a local branch has this state when an appropriate remote branch was
merged to a remote target branch and was removed. Since these manipulations were
made on server side, the local branch is still present, but useless.

2 - This kind of branches appears when a branch is created for some purposes but
does not have any commits nowadays. So, it is useless.

Approximate commands flow is
```bash
==>> git elegant prune-repository
git checkout master
git fetch --all
git branch --delete --force task-24
git branch --delete --force 2349
git branch --delete --force task-1
```

# `release-work`

```bash
Expand Down
36 changes: 1 addition & 35 deletions libexec/git-elegant
Original file line number Diff line number Diff line change
Expand Up @@ -40,40 +40,6 @@ _error-if-empty() {
fi
}

__loop_ask() {
local c="$1"; shift
local m="$1"; shift
[ -z "$1" ] && return 0
for i in $@; do
question-text "$m [$i] (y/n):"
read answer
if [[ "${answer}" == "y" ]]; then
eval "$c $i"
fi
done
}

__loop() {
local c="$1"; shift
[ -z "$1" ] && return 0
for i in $@; do
eval "$c $i"
done
}

__batch() {
local MM="$1"; shift
local AM="$1"; shift
local CM="$1"; shift
question-text "$MM (y/n): "
read answer
if [[ "${answer}" == "y" ]]; then
__loop "$CM" $@
else
__loop_ask "$CM" "$AM" $@
fi
}

branch-from-remote-reference() {
# usage: branch-from-remote-reference <full reference name>
echo ${1} | sed "s|^[a-zA-Z0-9_-]*/||g"
Expand Down Expand Up @@ -109,7 +75,7 @@ There are commands used in various situations such as
$(--print-command-in-usage clone-repository)
$(--print-command-in-usage init-repository)
$(--print-command-in-usage acquire-repository)
$(--print-command-in-usage clear-local)
$(--print-command-in-usage prune-repository)
manage a personal work
$(--print-command-in-usage start-work)
Expand Down
50 changes: 0 additions & 50 deletions libexec/git-elegant-clear-local

This file was deleted.

59 changes: 59 additions & 0 deletions libexec/git-elegant-prune-repository
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
#!/usr/bin/env bash
set -e

command-purpose() {
cat <<MESSAGE
Removes useless local branches.
MESSAGE
}

command-synopsis() {
cat <<MESSAGE
usage: git elegant prune-repository
MESSAGE
}

command-description() {
cat<<MESSAGE
Identifies useless branches within the current repository and removes them. A
branch is useless if it either has configured an unavailable upstream branch (1)
or does not have new commits comparing to \`master\` branch (2).
1 - Usually, a local branch has this state when an appropriate remote branch was
merged to a remote target branch and was removed. Since these manipulations were
made on server side, the local branch is still present, but useless.
2 - This kind of branches appears when a branch is created for some purposes but
does not have any commits nowadays. So, it is useless.
Approximate commands flow is
\`\`\`bash
==>> git elegant prune-repository
git checkout master
git fetch --all
git branch --delete --force task-24
git branch --delete --force 2349
git branch --delete --force task-1
\`\`\`
MESSAGE
}

default() {
git-verbose checkout ${MASTER}
git-verbose fetch --all
for branch in $(git for-each-ref --format "%(refname:short)" refs/heads/**); do
if [[ ${branch} == ${MASTER} ]]; then continue; fi
if [[ -n $(git config --get branch.${branch}.merge) ]]; then
if git rev-parse --abbrev-ref ${branch}@{upstream} >/dev/null 2>&1; then
# the branch has existing upstream; keep it
continue
fi
else
if [[ ! $(git merge-base ${MASTER} ${branch}) == $(git rev-parse ${branch}) ]]; then
# the branch has new commits; keep it
continue
fi
fi
git-verbose branch --delete --force ${branch}
done
}
32 changes: 0 additions & 32 deletions tests/git-elegant-clear-local.bats

This file was deleted.

50 changes: 50 additions & 0 deletions tests/git-elegant-prune-repository.bats
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#!/usr/bin/env bats -ex

load addons-common
load addons-read
load addons-fake
load addons-repo

setup() {
repo-new
}

teardown() {
fake-clean
repo-clean
}

@test "'prune-repository': a branch is removed when it doesn't have an upstream and new commits" {
repo "git checkout -b equal-to-master"
repo "git checkout master"
check git-elegant prune-repository
[[ ${status} -eq 0 ]]
[[ ${lines[@]} =~ "git branch --delete --force equal-to-master" ]]
}

@test "'prune-repository': a branch is alive when it doesn't have an upstream and has a new commit" {
repo "git checkout -b commit"
repo-commit-file "commit"
check git-elegant prune-repository
[[ ${status} -eq 0 ]]
[[ ! ${lines[@]} =~ "git branch --delete --force commit" ]]
}

@test "'prune-repository': a branch is removed when it has a gone upstream" {
repo "git checkout -b upstream"
repo "git checkout master"
fake-pass "git config --get branch.upstream.merge" "upstream"
fake-fail "git rev-parse --abbrev-ref upstream@{upstream}"
check git-elegant prune-repository
[[ ${status} -eq 0 ]]
[[ ${lines[@]} =~ "git branch --delete --force upstream" ]]
}

@test "'prune-repository': a branch is alive when it has an active upstream" {
repo "git checkout -b upstream"
fake-pass "git config --get branch.upstream.merge" "upstream"
fake-pass "git rev-parse --abbrev-ref upstream@{upstream}"
check git-elegant prune-repository
[[ ${status} -eq 0 ]]
[[ ! ${lines[@]} =~ "git branch --delete --force upstream" ]]
}
2 changes: 1 addition & 1 deletion tests/git-elegant-show-commands.bats
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ teardown() {
"deliver-work"
"accept-work"
"obtain-work"
"clear-local"
"prune-repository"
"show-commands"
"amend-work"
"show-release-notes"
Expand Down

0 comments on commit 47ea024

Please sign in to comment.