Git to Go; bindings for libgit2. Like McDonald's but tastier.

git2go

GoDoc Build Status

Go bindings for libgit2.

Which Go version to use

Due to the fact that Go 1.11 module versions have semantic meaning and don't necessarily align with libgit2's release schedule, please consult the following table for a mapping between libgit2 and git2go module versions:

libgit2 git2go
main (will be v34)
1.3 v33
1.2 v32
1.1 v31
1.0 v30
0.99 v29
0.28 v28
0.27 v27

You can import them in your project with the version's major number as a suffix. For example, if you have libgit2 v1.2 installed, you'd import git2go v33 with:

go get github.com/libgit2/git2go/v33
import "github.com/libgit2/git2go/v33"

which will ensure there are no sudden changes to the API.

The main branch follows the tip of libgit2 itself (with some lag) and as such has no guarantees on the stability of libgit2's API. Thus this only supports statically linking against libgit2.

Which branch to send Pull requests to

If there's something version-specific that you'd want to contribute to, you can send them to the release-${MAJOR}.${MINOR} branches, which follow libgit2's releases.

Installing

This project wraps the functionality provided by libgit2. It thus needs it in order to perform the work.

This project wraps the functionality provided by libgit2. If you're using a versioned branch, install it to your system via your system's package manager and then install git2go.

Versioned branch, dynamic linking

When linking dynamically against a released version of libgit2, install it via your system's package manager. CGo will take care of finding its pkg-config file and set up the linking. Import via Go modules, e.g. to work against libgit2 v1.2

import "github.com/libgit2/git2go/v33"

Versioned branch, static linking

Follow the instructions for Versioned branch, dynamic linking, but pass the -tags static,system_libgit2 flag to all go commands that build any binaries. For instance:

go build -tags static,system_libgit2 github.com/my/project/...
go test -tags static,system_libgit2 github.com/my/project/...
go install -tags static,system_libgit2 github.com/my/project/...

main branch, or vendored static linking

If using main or building a branch with the vendored libgit2 statically, we need to build libgit2 first. In order to build it, you need cmake, pkg-config and a C compiler. You will also need the development packages for OpenSSL (outside of Windows or macOS) and LibSSH2 installed if you want libgit2 to support HTTPS and SSH respectively. Note that even if libgit2 is included in the resulting binary, its dependencies will not be.

Run go get -d github.com/libgit2/git2go to download the code and go to your $GOPATH/src/github.com/libgit2/git2go directory. From there, we need to build the C code and put it into the resulting go binary.

git submodule update --init # get libgit2
make install-static

will compile libgit2, link it into git2go and install it. The main branch is set up to follow the specific libgit2 version that is vendored, so trying dynamic linking may or may not work depending on the exact versions involved.

In order to let Go pass the correct flags to pkg-config, -tags static needs to be passed to all go commands that build any binaries. For instance:

go build -tags static github.com/my/project/...
go test -tags static github.com/my/project/...
go install -tags static github.com/my/project/...

One thing to take into account is that since Go expects the pkg-config file to be within the same directory where make install-static was called, so the go.mod file may need to have a replace directive so that the correct setup is achieved. So if git2go is checked out at $GOPATH/src/github.com/libgit2/git2go and your project at $GOPATH/src/github.com/my/project, the go.mod file of github.com/my/project might need to have a line like

replace github.com/libgit2/git2go/v33 => ../../libgit2/git2go

Parallelism and network operations

libgit2 may use OpenSSL and LibSSH2 for performing encrypted network connections. For now, git2go asks libgit2 to set locking for OpenSSL. This makes HTTPS connections thread-safe, but it is fragile and will likely stop doing it soon. This may also make SSH connections thread-safe if your copy of libssh2 is linked against OpenSSL. Check libgit2's THREADSAFE.md for more information.

Running the tests

For the stable version, go test will work as usual. For the main branch, similarly to installing, running the tests requires building a local libgit2 library, so the Makefile provides a wrapper that makes sure it's built

make test-static

Alternatively, you can build the library manually first and then run the tests

make install-static
go test -v -tags static ./...

License

M to the I to the T. See the LICENSE file if you've never seen an MIT license before.

Authors

  • Carlos Martín (@carlosmn)
  • Vicent Martí (@vmg)
Owner
libgit2
A portable, pure C implementation of the Git core methods provided as a re-entrant linkable library with a solid API.
libgit2
Comments
  • HTTPS `Clone` fails with `remote pointer not found` using Go transport

    HTTPS `Clone` fails with `remote pointer not found` using Go transport

    Given:

    1. All tests (even Clone) initialize a Repository before they run a test
    2. The tests that make use of Clone seem to be using a local file path
    3. The limited number of examples available

    I am not really sure if this is due to a misuse of the API, or a bug. In any case, the following used to work before not too long ago with git2go/v31 and backing crypto / transport dependencies:

    func TestRemoteClone(t *testing.T) {
    	t.Parallel()
    	path, err := ioutil.TempDir("", "git2go")
    	if err != nil {
    		t.Fatalf("Failed to init temp dir")
    	}
    	defer os.RemoveAll(path)
    	remote, err := Clone("https://github.com/libgit2/libgit2", path, &CloneOptions{})
    	if err != nil {
    		t.Fatalf("Clone() = %v, want success", err)
    	}
    	defer remote.Free()
    }
    

    While attempting to update to git2go/v32 however, and trying to depend on less C libraries, this now returns a remote pointer not found error:

    === RUN   TestRemoteClone
    === PAUSE TestRemoteClone
    === CONT  TestRemoteClone
        remote_test.go:94: Clone() = remote pointer not found, want success
    --- FAIL: TestRemoteClone (0.00s)
    

    Following the breadcrumbs, it seems to end on https://github.com/libgit2/git2go/blob/main/clone.go#L43 returning -7 (which makes me wonder even more).

  • Double free error when cloning repository

    Double free error when cloning repository

    I'm still getting familiar with git2go and libgit2, but I did some digging and it seems git_clone() already does deallocate git_repository: https://github.com/libgit2/libgit2/blob/development/src/clone.c#L425. So, having this finalizer seems unnecessary: https://github.com/libgit2/git2go/blob/make-static/clone.go#L53

  • garbage collector found invalid heap pointer: Go 1.4

    garbage collector found invalid heap pointer: Go 1.4

    After upgrading from go1.3 to go1.4, I'd get a runtime crash most of the time. It crashes for various reasons (nil tree walker callback, invalid heap pointer...). Here is a scaled down version of the code that demonstrates the problem (runtime crashes most of the time). Run this code with an argument pointing at a git repository like git2go.

    package main
    
    import (
        "fmt"
        "github.com/libgit2/git2go"
        "os"
        "strings"
    )
    
    type MyRepo struct {
        *git.Repository
    }
    
    func (repository *MyRepo) foo(path string, treeEntry *git.TreeEntry) int {
        if git.ObjectBlob != treeEntry.Type {
            return 0 // continue
        }
    
        if !strings.HasSuffix(treeEntry.Name, ".go") {
            return 0 // continue
        }
    
        blob, err := repository.Repository.LookupBlob(treeEntry.Id)
        defer blob.Free()
        if err != nil {
            panic(err)
        }
    
        if blob.Size() > 10000 {
            return 0 // continue
        }
    
        contents := blob.Contents()
        if contents == nil {
            panic("nil contents")
        }
        fmt.Printf("%q", path, treeEntry.Name, string(contents))
        fmt.Println()
    
        return 0 // continue
    }
    
    func main() {
        filename := os.Args[1]
    
        repository, err := git.OpenRepository(filename)
        if err != nil {
            panic(err)
        }
        defer repository.Free()
    
        myRepo := MyRepo{repository}
    
        revWalk, err := repository.Walk()
        if err != nil {
            panic(err)
        }
        defer revWalk.Free()
    
        // Start out at the head
        err = revWalk.PushHead()
        if err != nil {
            panic(err)
        }
    
        err = revWalk.Iterate(func(commit *git.Commit) bool {
            defer commit.Free()
    
            tree, err := commit.Tree()
            if err != nil {
                panic(err)
            }
            defer tree.Free()
    
            err = tree.Walk(myRepo.foo)
            if err != nil {
                panic(err)
            }
    
            return true
        })
    
        if err != nil {
            panic(err)
        }
    }
    

    Some errors that come from the above code:

    panic: runtime error: invalid memory address or nil pointer dereference
    [signal 0xb code=0x1 addr=0x0 pc=0x40f4299]
    
    goroutine 1 [running]:
    github.com/libgit2/git2go.CallbackGitTreeWalk(0x438a520, 0x51008e0, 0xc208071e40, 0x0)
        /Users/maleticm/.gvm/pkgsets/go1.4/jack/src/github.com/libgit2/git2go/tree.go:99 +0x79
    github.com/libgit2/git2go._Cfunc__go_git_treewalk(0x5100850, 0x0, 0xc208069e40, 0x0)
        /Users/maleticm/.gvm/pkgsets/go1.4/jack/src/github.com/libgit2/git2go/:402 +0x43
    github.com/libgit2/git2go.Tree.Walk(0x5100850, 0xc20802c018, 0x5100850, 0xc208069e80, 0x0, 0x0)
    
    runtime: garbage collector found invalid heap pointer *(0xc208069cd0+0x10)=0xc208083e40 span=0xc20807e000-0xc208083800-0xc208084000 state=0
    fatal error: invalid heap pointer
    
    runtime stack:
    runtime.throw(0x437df83)
        /Users/maleticm/.gvm/gos/go1.4/src/runtime/panic.go:491 +0xad fp=0x7fff5fbfea18 sp=0x7fff5fbfe9e8
    scanblock(0xc208069cd0, 0x20, 0x42c12e4)
        /Users/maleticm/.gvm/gos/go1.4/src/runtime/mgc0.c:378 +0x551 fp=0x7fff5fbfeb58 sp=0x7fff5fbfea18
    scanframe(0x7fff5fbfec60, 0x0, 0x1)
        /Users/maleticm/.gvm/gos/go1.4/src/runtime/mgc0.c:740 +0x1c2 fp=0x7fff5fbfebc8 sp=0x7fff5fbfeb58
    
    unexpected fault address 0xb01dfacedebac1e
    fatal error: fault
    [signal 0xb code=0x1 addr=0xb01dfacedebac1e pc=0x40f4299]
    
    goroutine 1 [running, locked to thread]:
    runtime.gothrow(0x426ec90, 0x5)
        /Users/maleticm/.gvm/gos/go1.4/src/runtime/panic.go:503 +0x8e fp=0xc208069c40 sp=0xc208069c28
    runtime.sigpanic()
        /Users/maleticm/.gvm/gos/go1.4/src/runtime/sigpanic_unix.go:29 +0x261 fp=0xc208069c90 sp=0xc208069c40
    github.com/libgit2/git2go.CallbackGitTreeWalk(0x438a520, 0x5009680, 0xc208073e40, 0x0)
    
  • could not determine kind of name for C.GIT_CHECKOUT_SAFE_CREATE

    could not determine kind of name for C.GIT_CHECKOUT_SAFE_CREATE

    commit 98793509039cc80b774c527d9e5a7b5d70e3b6c4
    Author: Shawn Landden <[email protected]>
    Date:   Sat Mar 14 15:42:25 2015 -0700
    
        GIT_CHECKOUT_SAFE_CREATE has been removed in libgit2
    
        Signed-off-by: Shawn Landden <[email protected]>
    
    diff --git a/checkout.go b/checkout.go
    index 6eb6098..9456168 100644
    --- a/checkout.go
    +++ b/checkout.go
    @@ -15,7 +15,6 @@ type CheckoutStrategy uint
     const (
            CheckoutNone                      CheckoutStrategy = C.GIT_CHECKOUT_NONE                         // Dry run, no actual updates
            CheckoutSafe                      CheckoutStrategy = C.GIT_CHECKOUT_SAFE                         // Allow safe updates that cannot overwrite uncommitted data
    -       CheckoutSafeCreate                CheckoutStrategy = C.GIT_CHECKOUT_SAFE_CREATE                  // Allow safe updates plus creation of missing files
            CheckoutForce                     CheckoutStrategy = C.GIT_CHECKOUT_FORCE                        // Allow all updates to force working directory to look like index
            CheckoutAllowConflicts            CheckoutStrategy = C.GIT_CHECKOUT_ALLOW_CONFLICTS              // Allow checkout to make safe updates even if conflicts are found
            CheckoutRemoveUntracked           CheckoutStrategy = C.GIT_CHECKOUT_REMOVE_UNTRACKED             // Remove untracked files not in index (that are not ignored)
    
  • Consider making this package go gettable?

    Consider making this package go gettable?

    Right now, this package requires custom manual steps for its installation:

    Run go get -d github.com/libgit2/git2go to download the code and go to your $GOPATH/src/github.com/libgit2/git2go dir. From there, we need to build the C code and put it into the resulting go binary.

    git submodule update --init # get libgit2
    make install
    

    will compile libgit2 and run go install such that it's statically linked to the git2go package.

    This is inconvenient, it makes it harder to get than other Go packages (which are just go get). Worst of all, this means that any other Go package that imports this one, even if the upstream package is completely go gettable, will no longer be 1 command to install.

    I think it may be possible for you to change that, and thus improve the experience of anyone using this packages, and make it easy for others to import it and no incur the cost of manual dependency installation steps.

    The way you can do that would be similar to how we did it with glfw3 package (currently on a branch, to be merged into master once GLFW 3.1 is released), which is a Go binding for a C library. It was discovered by @slimsag and you can see the discussion in the following issue and PR:

    https://github.com/go-gl/glfw3/issues/82 https://github.com/go-gl/glfw3/pull/83

    The general idea is that you vendor the C library source in a subfolder (potentially as a git submodule) and use cgo directives to link to it. Basically, everything you're doing now, except without needing the Makefile and scripts.

    The main consideration is that you will need to replace the function of CMake with multiple .go files with build tags (which may require some work and maintenance), which is what we've done in glfw3:

    Less configurable? Unable to modify CMAKE parameters?

    Actually -- We can make build tags for any CMAKE configurable feature that we want (e.g. tell people to compile their application with go install -tags "wayland" my/pkg and a wayland client will be built instead of an X11 one, you can see how I did this here: https://github.com/go-gl/glfw3/blob/devel_glfw3.1/build.go)

    But the end result is a go gettable package that is much easier for users. Just imagine:

    To install git2go, run go get -u github.com/libgit2/git2go. Done.

    What do you think? If this is something you're amendable to, I can assist with questions/answers about the approach and potentially try to make a PR.

  • Move to statically link libgit2

    Move to statically link libgit2

    This also adds a submodule so we know which version of libgit2 we're building against. Statically linking libgit2 gets us closer to the way Go does things.

    We do however still link dynamically with libgit2's dependencies, namely openssl and libssh2 if available.

  • [TEST MISSING] Add function to init repos w/custom odb backends

    [TEST MISSING] Add function to init repos w/custom odb backends

    Add function in repository.go to initialize a repository with a custom ODB backend.

    I am unsure how to write tests for this, as the test environment would require a custom ODB backend.

    In the meantime, you can install my Kyoto Tycoon backend from https://github.com/anulman/libgit2/tree/kyoto (set -DGIT_ODB_KYOTO=ON before building) and use the following routine to test:

    package main
    
    /*
    #cgo pkg-config: libgit2
    #include <git2.h>
    #include <git2/backends/kyotoTycoon/odb_kyoto.h>
    */
    import "C"
    import (
        "errors"
        "fmt"
        "github.com/libgit2/git2go"
        "os"
        "unsafe"
    )
    
    const kyotoPath string = "http://localhost:1978/"
    
    func main() {
        // define initStrategy abstract function for custom backend init
        initStrategy := func(repo **C.git_repository, odb **C.git_odb) (ret int) {
            // convert path for use in c
            cpath := C.CString(kyotoPath)
            defer C.free(unsafe.Pointer(cpath))
    
            // handoff to c, convert C.int to int for error check
            cret := C.git_odb_backend_wrap_kyoto(repo, odb, cpath)
            ret = int(cret)
    
            return
        }
    
        _, odb, err := git.InitRepositoryWCustomOdbBackend(initStrategy)
        defer odb.Free()
    
        if err != nil {
            fmt.Println(err)
            return
        }
    
        if len(os.Args) < 3 {
            err = errors.New("call with (w)rite/(r)ead + data/oid")
            fmt.Println(err)
            return
        }
    
        if os.Args[1] == "write" || os.Args[1] == "w" {
            oid, err := odb.Write([]byte(os.Args[2]), git.ObjectBlob)
            if err == nil {
                fmt.Println("oid:", oid)
                return
            }
        } else if os.Args[1] == "read" || os.Args[1] == "r" {
            oid, err := git.NewOidFromString(os.Args[2])
            if err == nil {
                obj, err := odb.Read(oid)
                if err == nil {
                    fmt.Println("obj data:", string(obj.Data()))
                    return
                }
            }
        } else {
            fmt.Println("unrecognized command:", os.Args[1])
        }
    
        if err != nil {
            fmt.Println(err)
            return
        }
    }
    

    run with:

    go run [file] w [string]
    go run [file] r [returned oid]
    
  • libgit2 version check

    libgit2 version check

    During compilation git2go performs the following libgit2 version check:

    https://github.com/libgit2/git2go/blob/ad3ec3664d54779c4c2e49e41f85e886fbff343c/git_system_dynamic.go#L10-L12

    Suppose I want to install a go software which uses git2go through go get on both Ubuntu 20.04 and Arch Linux I would run into the following problem: These Linux distributions ship different versions of libgit2. Since the version check performed by git2go is very strict (requiring an exact match of both minor and major version) the aforementioned go software would only compile with one specific version of libgit2, according to the version suffix I used for the git2go import.

    IMHO it would be desirable if the git2go version check would be less strict. If I am informed correctly, libgit2 uses semantic versioning. As such, the API should not change in backwards incompatible ways without a major version bump. For instance, github.com/libgit2/git2go/v30 (which currently requires libgit2 1.0.0) should IMHO compile with any libgit2 version where LIBGIT2_VER_MAJOR == 1 and LIBGIT2_VER_MINOR >= 0 (e.g. should compile fine with both libgit2 1.1.0 and libgit2 1.0.0).

  • [WIP/RFC] Pointer indirection

    [WIP/RFC] Pointer indirection

    This pull request fixes issues with Go callbacks that are handed over to C functions. As of Go 1.4 it is not possible to hand over Go pointers into C code as the garbage collector is allowed to copy around the stack, causing pointers to become invalid (see golang/go#8310 and golang/go#10303 for more information).

    @carlosmn proposed an interface HandleList for pointer indirection which provides a global map of data that is to be tracked. Instead of handing in pointers we now instead hand over an index that points to the corresponding entry in this map.

    This PR adds the HandleList implemented by @carlosmn, fixes some issues with it and adjusts code that hands over Go pointers into C code to use handles instead. Still missing is the remote.go code, as I am running into some error there ('runtime: garbage collector found invalid heap pointer *(0xc208063cd0+0x18)=0x1 s=nil') that I've not been able to fix.

    This PR also fixes #163.

  • Issue with homebrew installed libgit2

    Issue with homebrew installed libgit2

    When I install libgit2 using homebrew and then try to go build git2go I get the following error:

    # github.com/libgit2/git2go
    37: error: use of undeclared identifier 'git_remote_create_cb'; did you mean 'git_remote_create'?
    
  • Use of $LD_LIBRARY_PATH

    Use of $LD_LIBRARY_PATH

    Hi team!

    I am creating a funny library with git2go/libgit2: gitql. But I think that set $LD_LIBRARY_PATH everytime before run it is a bad idea :confused: I would like know if there is other way because set that variable globally seems bad too

    Thanks! And congrats for this bind! :smile:

  • Replace golang.org/x/crypto/openpgp with github.com/ProtonMail/go-crypto

    Replace golang.org/x/crypto/openpgp with github.com/ProtonMail/go-crypto

    The golang.org/x/crypto/openpgp library has been deprecated for over a year now (see https://golang.org/issue/44226, and the deprecation notice in the package documentation). The library is unmaintained and has a number of API and usability issues. ProtonMail maintains a community fork which is actively maintained, and for most cases is a drop-in replacement.

    This change switches usages of golang.org/x/crypto/openpgp/... with github.com/ProtonMail/go-crypto/openpgp/..., the only other code changes are adding a nil packet.Config to a openpgp.CheckArmoredDetachedSignature call.

    (This change is part of a wider effort by the Go Security team to remove usages of golang.org/x/crypto/openpgp from the Go ecosystem.)

  • Mapping examples between libgit2 and git2go in README need to be updated

    Mapping examples between libgit2 and git2go in README need to be updated

    In this list:

    https://github.com/libgit2/git2go#which-go-version-to-use

    One should use libgit2 v1.5 with git2go v34

    The text implies libgit2 v1.2 with git2go v34

    "You can import them in your project with the version's major number as a suffix. For example, if you have libgit2 v1.2 installed, you'd import git2go v34 with:"

    I updated the two relevant sentences in this PR https://github.com/libgit2/git2go/pull/939

  • Is this repository still active?

    Is this repository still active?

    There are many Pull Requests open, but none of them reviewed or even commented except old ones. I see that there was a new release few days ago, but it could include these improvements from me #926 and for example from @clns with #913. Now these features will postponed again maybe forever. Can someone review this backlog or this project is archived and don't accept new features?

    cc @lhchavez @carlosmn

A CLI to replace your git commit command, so your git message can partially follow the Conventional Changelog ecosystem
A CLI to replace your git commit command, so your git message can partially follow the Conventional Changelog ecosystem

COMMIT CLI A CLI to replace your git commit command, so your git message can partially follow the Conventional Changelog ecosystem. And yes, it is bui

Feb 9, 2022
lsp is like ls command but more human-friendly
lsp is like ls command but more human-friendly

lsp: list files in a mildly human-frendlier manner lsp lists files, like ls command, but it does not attempt to meet that archaic POSIX specification,

Dec 12, 2022
🎭👄 Like cowsay but it's random anime quote
🎭👄 Like cowsay but it's random anime quote

?? ?? weebsay - cowsay but it's random anime quote ?? aesthetics inspired by TorchedSammy follow him he is a good guy Installation ?? go get -u github

Dec 11, 2022
car is like tar, but for containers!

Mainly, car lets you list or extract files from an OCI (possibly Docker) image, regardless of the platform it was built for. For example, you can extract files from a windows/amd64 image even if you are running linux/arm64.

Nov 26, 2022
Modern ls command with vscode like File Icon and Git Integrations. Written in Golang
Modern ls command with vscode like File Icon and Git Integrations. Written in Golang

logo-ls modern ls command with beautiful Icons and Git Integrations . Written in Golang Command and Arguments supported are listed in HELP.md Table of

Dec 29, 2022
Flag is a simple but powerful command line option parsing library for Go support infinite level subcommand

Flag Flag is a simple but powerful commandline flag parsing library for Go. Documentation Documentation can be found at Godoc Supported features bool

Sep 26, 2022
Query, update and convert data structures from the command line. Comparable to jq/yq but supports JSON, TOML, YAML, XML and CSV with zero runtime dependencies.
Query, update and convert data structures from the command line. Comparable to jq/yq but supports JSON, TOML, YAML, XML and CSV with zero runtime dependencies.

dasel Dasel (short for data-selector) allows you to query and modify data structures using selector strings. Comparable to jq / yq, but supports JSON,

Jan 2, 2023
😎 Yet Another yes clone but in Golang

Yeah Output a string repeatedly until killed. Yet Another yes clone but in Golang. Usage Just like yes: yeah This will print "y" until the process is

Apr 7, 2022
Go-Suit is a very very wacky version of a bash terminal but in go, however with a little twitst

Go-Suit Go-Suit is a very very wacky version of a bash terminal but in go, however with a little twitst languages -> Go-Lang packages Third Party -> g

May 19, 2022
Go-dura - Tim Kellogg's Dura but written in Go

go-dura Tim Kellogg's Dura but written in Go I encourage anyone with Rust knowle

May 9, 2022
Count once - Just once? no, when appear many it run once, but it can run many times

countOnce just once? no, when appear many it run once, but it can run many times

Jan 29, 2022
A lightweight but powerful OCR tool.
A lightweight but powerful OCR tool.

这个项目是什么? LOCR(Lightweight OCR)是一款轻量级的文字识别工具, 结合第三方截图工具, 可以快速的对图片文字进行识别。 为什么有这个项目 在日常学习的工作中, 难免会遇到一些文字的复制粘贴任务。但由于一些限制,我们无法复制想要的文字,只能一个字一个字的敲出来。而随着近几年OC

Nov 1, 2022
Simple, seamless, lightweight time tracking for Git
Simple, seamless, lightweight time tracking for Git

Git Time Metric Seamless time tracking for all your Git projects $ gtm report -last-month $ gtm report -last-month -format summary $ gtm report -last-

Dec 27, 2022
commit/branch/workdir explorer for git

gitin gitin is a commit/branch/status explorer for git gitin is a minimalist tool that lets you explore a git repository from the command line. You ca

Dec 21, 2022
A tiny git forge written in Go

Smithy smithy (n) A blacksmith's shop; a forge. Smithy is a web frontend for git repositories. It's implemented entirely in Golang, compiles to a sing

Jan 5, 2023
💊 A git query language

Gitql Gitql is a Git query language. In a repository path... See more here Reading the code ⚠️ This project was created in 2014 as my first go project

Dec 29, 2022
git-xargs is a command-line tool (CLI) for making updates across multiple Github repositories with a single command.
git-xargs is a command-line tool (CLI) for making updates across multiple Github repositories with a single command.

Table of contents Introduction Reference Contributing Introduction Overview git-xargs is a command-line tool (CLI) for making updates across multiple

Dec 31, 2022
A better way to clone, organize and manage multiple git repositories
A better way to clone, organize and manage multiple git repositories

git-get git-get is a better way to clone, organize and manage multiple git repositories. git-get Description Installation macOS Linux Windows Usage gi

Nov 16, 2022
Bit is a modern Git CLI
Bit is a modern Git CLI

bit is an experimental modernized git CLI built on top of git that provides happy defaults and other niceties: command and flag suggestions to help yo

Dec 28, 2022