Skip to content

daniel-fanjul-alcuten/git-greb

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

46 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Description

It gets a list of all local git branches, gets their tracking branches -local or remote-, builds a graph of dependencies and runs 'git pull' for them in order.

It is a different approach to TopGit commands: update and export.

Installation

Use 'go get':

go get github.com/daniel-fanjul-alcuten/git-greb

Update

Use 'go get -u'

go get -u github.com/daniel-fanjul-alcuten/git-greb

Usage

Usage of git-greb [<options>] [<branches>]:

git-greb builds a graph of dependencies of the local branches. They usually depend
on remote branches but they also can track other local branches. The graph is
defined using the usual git config options branch.<name>.remote and
branch.<name>.merge.

git-greb supports branches that track multiple branches at the same time. In git
there is only one value of the remote option for one or more merge options;
git-greb takes this into account.

The arguments are processed with git rev-parse to discover the abbreviated name
of the branches. If there are no arguments, all local branches are retrieved
instead. Then git-greb queries recursively the remote and merge tracking options
to discover the dependencies and build the graph.

The first set of options makes git-greb dump the graph in the standard output in
different formats and then exit:

     -t=false: it uses a custom text format (text graph).
   -dot=false: it uses the dot format (dot graph).
     -x=false: it draws the dot format in an xlib window (xlib graph).

The second set of options makes git-greb traverse the graph visiting the branches
in order from the downstreams to the upstreams and running some variant of 'git
pull' on them. If no option is provided 'git pull' merges or rebases depending
on the usual git options.

     -r=false: it pulls every branch with --rebase (rebase).
     -m=false: it pulls every branch with --no-rebase (merge).
     -i=false: it rebases with --interactive (interactive).
     -c=false: it checks out instead of pulling (checkout).
     -s=false: it does not pull at all (skip).

The option -d makes git-greb delete branches that don't create new history
over their tracking branches. None is deleted until all of them have been
successfuly updated in the previous step. A branch is deleted if it points to
the same commit as at least one of its upstream branches. They are deleted in
the opposite order.

The tracking configuration is updated accordingly: if a set of branches A
depends on a branch B, B depends on a set of branches C, and B is eligible for
deletion: all branches A stop tracking B and start tracking the branches C.

     -d=false: it deletes fully merged branches after pulling (delete).

The option -l makes git-greb pull only those branches that don't have any
upstream branch in a different repository from the local one.

     -l=false: it only pulls local tracking branches (local).

git-greb checks out every branch before pulling and stops when a command doesn't
finish with exit status 0. If all pulls finish successfully git-greb tries to
return to the original branch. The option -C may be used to return to a
different one. As the branch may have been deleted or any command may have
failed, the user should expect that the current branch may be different or even
that the HEAD may become detached. git-greb tries to minimize the number of
checkouts.

     -C=HEAD: it checks out the given branch before exit (change branch).

Other options:

     -q=false: it does not print the command lines (quiet).
     -v=false: it explains intermediate steps (verbose).
     -n=false: it does not run any command (noop).
  -bash=: name of the bash function to use with complete (bash completion)

git-greb checks the following options in the usual git configuration files:

  greb.local:         If the option -l is false, this bool option is used
                      instead.
  color.greb:         It enables or disables color in git-greb. See color.ui for
                      more information.
  color.greb.command: The color of the git commands that the user needs to know
                      that have been run. Blue by default.
  color.greb.current: The color of the current branch. Green by default.
  color.greb.remote:  The color of the branches in other repositories. Red by
                      default.

Example

These git and git-greb commands:

dir1=git-greb1.git
rm -rf /tmp/$dir1
git init --bare /tmp/$dir1
cd /tmp/$dir1

dir2=git-greb2.git
rm -rf /tmp/$dir2
git clone /tmp/$dir1 /tmp/$dir2
cd /tmp/$dir2
git config pull.rebase true
git config greb.local false

touch master
git add master
git commit -m "file master"
git push -u origin master

git checkout -b foo -t master
touch foo; git add foo; git commit -m "file foo"
git status --short --branch
## foo...master [ahead 1]

git checkout -b bar -t master
touch bar; git add bar; git commit -m "file bar"
git branch -u foo
git status --short --branch
## bar...foo [ahead 1, behind 1]

git checkout -b baz -t master
touch baz; git add baz; git commit -m "file baz"
git branch -u foo
git status --short --branch
## baz...foo [ahead 1, behind 1]

git checkout -b qux -t bar
git config --add branch.qux.merge baz
git status --short --branch
## qux...bar
## qux...baz

git-greb -d
# it pulls master (noop)
# it pulls foo (noop)
# it pulls bar (rebase onto foo)
# it pulls baz (rebase onto foo)
# it pulls qux (octopus of bar and baz)
# it deletes master (making foo follow origin/master)

git push origin bar:master
# it pushes foo and bar

git-greb -d
# it pulls foo (fast forward)
# it pulls bar (noop)
# it pulls baz (rebase onto foo)
# it pulls qux (octopus of bar and baz)
# it deletes bar (making qux follow foo)
# it deletes foo (making baz follow origin/master)

git rebase -f baz qux
# it kills the merge

git-greb -d
# it pulls baz (noop)
# it pulls qux (noop)
# it deletes qux

generate this output:

+ dir1=git-greb1.git
+ rm -rf /tmp/git-greb1.git
+ git init --bare /tmp/git-greb1.git
Initialized empty Git repository in /tmp/git-greb1.git/
+ cd /tmp/git-greb1.git
+ dir2=git-greb2.git
+ rm -rf /tmp/git-greb2.git
+ git clone /tmp/git-greb1.git /tmp/git-greb2.git
Cloning into '/tmp/git-greb2.git'...
warning: You appear to have cloned an empty repository.
done.
+ cd /tmp/git-greb2.git
+ git config pull.rebase true
+ git config greb.local false
+ touch master
+ git add master
+ git commit -m file master
[master (root-commit) b704a57] file master
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 master
+ git push -u origin master
To /tmp/git-greb1.git
 * [new branch]      master -> master
Branch master set up to track remote branch master from origin.
+ git checkout -b foo -t master
Switched to a new branch 'foo'
Branch foo set up to track local branch master.
+ touch foo
+ git add foo
+ git commit -m file foo
[foo 4643cb6] file foo
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 foo
+ git status --short --branch
## foo...master [ahead 1]
+ git checkout -b bar -t master
Switched to a new branch 'bar'
Branch bar set up to track local branch master.
+ touch bar
+ git add bar
+ git commit -m file bar
[bar 40938b2] file bar
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 bar
+ git branch -u foo
Branch bar set up to track local branch foo.
+ git status --short --branch
## bar...foo [ahead 1, behind 1]
+ git checkout -b baz -t master
Switched to a new branch 'baz'
Branch baz set up to track local branch master.
+ touch baz
+ git add baz
+ git commit -m file baz
[baz 24a0dcc] file baz
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 baz
+ git branch -u foo
Branch baz set up to track local branch foo.
+ git status --short --branch
## baz...foo [ahead 1, behind 1]
+ git checkout -b qux -t bar
Switched to a new branch 'qux'
Branch qux set up to track local branch bar.
+ git config --add branch.qux.merge baz
+ git status --short --branch
## qux...bar
+ /home/dfanjul/lib/go/bin/git-greb -d
greb: git checkout master
Switched to branch 'master'
Your branch is up-to-date with 'origin/master'.
greb: git pull
Current branch master is up to date.
greb: git checkout foo
Switched to branch 'foo'
Your branch is ahead of 'master' by 1 commit.
greb: git pull
From .
 * branch            master     -> FETCH_HEAD
Current branch foo is up to date.
greb: git checkout baz
Switched to branch 'baz'
Your branch and 'foo' have diverged,
and have 1 and 1 different commit each, respectively.
greb: git pull
From .
 * branch            foo        -> FETCH_HEAD
First, rewinding head to replay your work on top of it...
Applying: file baz
greb: git checkout bar
Switched to branch 'bar'
Your branch and 'foo' have diverged,
and have 1 and 1 different commit each, respectively.
greb: git pull
From .
 * branch            foo        -> FETCH_HEAD
First, rewinding head to replay your work on top of it...
Applying: file bar
greb: git checkout qux
Switched to branch 'qux'
Your branch and 'bar' have diverged,
and have 1 and 2 different commits each, respectively.
greb: git pull --no-rebase
From .
 * branch            bar        -> FETCH_HEAD
 * branch            baz        -> FETCH_HEAD
Trying simple merge with 59dff2da40e58fc926781565252ef4af5e71dbb7
Trying simple merge with 447c500c940317ebf0c2483ecb891d97da599ac3
Merge made by the 'octopus' strategy.
greb: git branch -D master
Deleted branch master (was b704a57).
greb: git config --unset branch.foo.merge ^refs/heads/master$
greb: git config branch.foo.remote origin
greb: git config --add branch.foo.merge refs/heads/master
+ git push origin bar:master
To /tmp/git-greb1.git
   b704a57..59dff2d  bar -> master
+ /home/dfanjul/lib/go/bin/git-greb -d
greb: git checkout foo
Switched to branch 'foo'
Your branch is behind 'origin/master' by 1 commit, and can be fast-forwarded.
greb: git pull
First, rewinding head to replay your work on top of it...
Fast-forwarded foo to 59dff2da40e58fc926781565252ef4af5e71dbb7.
greb: git checkout baz
Switched to branch 'baz'
Your branch and 'foo' have diverged,
and have 1 and 1 different commit each, respectively.
greb: git pull
From .
 * branch            foo        -> FETCH_HEAD
First, rewinding head to replay your work on top of it...
Applying: file baz
greb: git checkout bar
Switched to branch 'bar'
Your branch is up-to-date with 'foo'.
greb: git pull
From .
 * branch            foo        -> FETCH_HEAD
Current branch bar is up to date.
greb: git checkout qux
Switched to branch 'qux'
Your branch is ahead of 'bar' by 3 commits.
greb: git pull --no-rebase
From .
 * branch            bar        -> FETCH_HEAD
 * branch            baz        -> FETCH_HEAD
Merge made by the 'recursive' strategy.
greb: git branch -D bar
Deleted branch bar (was 59dff2d).
greb: git config --unset branch.qux.merge ^refs/heads/bar$
greb: git config --add branch.qux.merge refs/heads/foo
greb: git branch -D foo
Deleted branch foo (was 59dff2d).
greb: git config --unset branch.baz.merge ^refs/heads/foo$
greb: git config branch.baz.remote origin
greb: git config --add branch.baz.merge refs/heads/master
greb: git config --unset branch.qux.merge ^refs/heads/foo$
+ git rebase -f baz qux
First, rewinding head to replay your work on top of it...
Applying: file bar
Using index info to reconstruct a base tree...
Falling back to patching base and 3-way merge...
No changes -- Patch already applied.
Applying: file baz
Using index info to reconstruct a base tree...
Falling back to patching base and 3-way merge...
No changes -- Patch already applied.
+ /home/dfanjul/lib/go/bin/git-greb -d
greb: git checkout baz
Switched to branch 'baz'
Your branch is ahead of 'origin/master' by 1 commit.
greb: git pull
Current branch baz is up to date.
greb: git checkout qux
Switched to branch 'qux'
Your branch is based on 'baz', but the upstream is gone.
greb: git pull
From .
 * branch            baz        -> FETCH_HEAD
Current branch qux is up to date.
greb: git checkout --detach
HEAD is now at 35b702d... file baz
greb: git branch -D qux
Deleted branch qux (was 35b702d).

About

Graph of REBases

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages