Generic, high-level Git workflow support!

Git Town

CircleCI Go Report Card License Help Contribute to Open Source

Git Town makes Git more efficient, especially for large teams. See this screencast for an introduction and this Softpedia article for an independent review.

Commands

Git Town provides these additional Git commands:

Development Workflow

Repository Maintenance

Git Town Configuration

Git Town Installation

Installation

See the installation instructions for more details.

Aliasing

Git Town commands can be aliased to remove the town prefix:

git town alias true

After executing this, you can run git hack instead of git town hack. You can also set this manually for individual commands:

git config --global alias.hack 'town hack'

Configuration

Git Town prompts for required configuration information during usage. Use the git town config command to manage the stored configuration.

Required configuration

Optional Configuration

These configuration options have defaults, so the configuration wizard does not ask about them.

  • pull branch strategy

    • how to sync the main branch / perennial branches with their upstream
    • default: rebase
    • possible values: merge, rebase
  • new branch push flag

    • whether or not branches created by hack / append / prepend should be pushed to remote repo
    • default: false
    • possible values: true, false

Documentation

Run git town for an overview of the Git Town commands and git help <command> (e.g. git help sync) for help with individual commands.

Q&A

  • Is this compatible with my workflow?
    Yes. Git Town is compatible with GitHub Flow, Git Flow, the Nvie model, GitLab Flow, and most others workflows.

  • Does my whole team have to use Git Town?
    No. Just make sure that all feature branches get squash-merged, for example by requiring this in your GitHub settings. If you don't know what squash-merges are, you probably want to enable them.

Contributing

Found a bug or have an idea for a new feature? Open an issue or send a pull request! Check out our contributing and developer guides to get started.

Sponsors

Thanks to our sponsors for their continued support!

Contributors

Kudos to our contributors!

@kevgo @charlierudolph @allewun @ricmatsui @redouglas @allonsy @blaggacao
@aricahunter @jiexi @iamandrewluca @ChrisMM @zhangwei @tallpants @seanstrom
@schneems @morrme @mjhm @luketlancaster @ecbrodie @doismellburning @dgjnpr
@atilacamurca @Zearin @TKAB @Siilwyn @WurmD @sgarfinkel @cirego
@sheldonhull @alphatroya @joshRpowell @pattiereaves @zenspider
@Iron-Ham
@grignaak
@ericyliu @natecox @shadowhand @hmbrg @qrevel @aeneasr @martinjaime
@alexw10 @alexdavid @Braunson

Stargazers over time

Stargazers over time

Comments
  • make squash merge work with github flow

    make squash merge work with github flow

    @Bowbaq had a good idea. since git town likes to squash merge, but it closes your PR rather than merging... what if the flow was: git reset master -> make a single commit (the same commit that would be your squash commit) -> force push to your pull request -> click merge on github. this would allow other tools that look at the status of a pull request to still recognize when PRs get merged in.

  • Run in the Git root directory

    Run in the Git root directory

    @charlierudolph @allewun

    This implements #371

    This is a "best effort" implementation for the case that the user runs "git sync" in a folder that doesn't exist on main.

    The previous implementation crashes, and is unable to continue or abort, thereby at best leaving the user in a very confusing state (in a non-existing directory, without any Git functionality), and at worst losing stashed away changes.

    With these changes, the Git Town command at least finishes properly. The user shell is still in limbo, but the user can cd back into his directory manually. CD'ing in the script doesn't help because it doesn't change the parent shell.

    Unfortunately I can't test this. When you are in a folder that doesn't exist on main, and Git changes to the main branch, it physically removes that folder from the hard drive. This leaves any parent process in limbo, be it your Bash/Fish shell or the surrounding Cucumber tester. Further Git or file operations are impossible. As a second-best solution, I have documented the issue in the code base to motivate and justify the respective changes.

    This is still a good change imho, since it improves the reliability and robustness of Git Town in edge cases, and in general is the right thing to do.

    Steps to reproduce the issue:

    • git hack test
    • mkdir foo ; cd foo ; touch bar
    • git add -A ; git commit -m "test"
    • git sync
  • git ship: add

    git ship: add "closes #[PR number]" to the description of shipped branches

    Github automatically closes and references PRs when adding Closes #[Some PR] to a commit. Having git ship automatically append this to the squashed merge commit would help automate the entire feature branch processes.

  • Fish install script

    Fish install script

    @charlierudolph @allewun

    This provides an easy command git town install-fish-autocompletion to install the fish shell autocompletion. This command is pretty bare bones right now, but should be all we need. Later if there is demand we can add handling of custom Fish setups etc.

    Implements #284

  • "non-feature" branch naming

    I was thinking about the naming we use... I believe we can come up with a better name. The "non-" negation makes it a bit confusing when trying to reason about the meaning of a "non-feature branch".

    We have three classes of branches now: 1) main, 2) feature, 3) non-feature.

    Main and non-feature are treated similarly in many aspects, but when you see the words side-by-side, at first glance they feel like opposing classes, which is a bit misleading. This is especially apparent in the git town config output.

    The naming just doesn't feel very fitting or intuitive to me. I see that "special" was considered at one point (https://github.com/Originate/git-town/pull/57). I think something similar to that would be more appropriate.

    A likely positive side-effect would be having a shorter single-word name, for better symmetry with "main" (regarding https://github.com/Originate/git-town/pull/334).

    Thoughts?

  • Output rework

    Output rework

    Change the output of each command to simply output each git command in bold and the output of that command immediately after.

    Cleanup error messages to follow suit of what git rebase errors look like (but print in red to easily catch the eye).

    To get a look, run a single cucumber test with the commands printed out. cucumber features/git-ship.feature:3 DEBUG=true

  • Support rebase strategy for `sync` and `new-pull-request`

    Support rebase strategy for `sync` and `new-pull-request`

    GitHub now allows us to require a linear history which prevents merge commits from being pushed to matching branches:

    Bildschirmfoto 2020-05-07 um 11 51 15

    Because of the way git sync works, we end up with merge commits in between our commits if the main dev branch had updates. This in turn can cause the "rebase" merge option on GitHub to not be available. I believe this happens when merge conflicts have been resolved.

    This then conflicts with the linear commit history dictated by the branch protection rule, leaving only "Squash & Rebase" as a viable merge strategy which destroys our beautiful commit messages!

    Therefore, I would like to be able to tell git-town to use git pull --rebase (or whatever it is doing under the hood) instead of git pull when doing git-town sync

    More context:

    • https://help.github.com/en/github/administering-a-repository/requiring-a-linear-commit-history
    • https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/about-pull-request-merges
  • Merge verifying commits and files

    Merge verifying commits and files

    @charlierudolph @allewun

    This PR dries up the verification of unchanged commits, by re-using the commit table that was originally defined in the beginning of a feature.

    In order to make that happen, I had to merge the command and file content comparison. Which is naturally anyways imho.

  • Finish implementing #98 (encapsulate configuration)

    Finish implementing #98 (encapsulate configuration)

    @charlierudolph @kevgo

    • Added ability to run git town [...] even before configuring git town.
      • Rationale - the user should be able to see the help text before being immediately prompted by the config prompts
    • Added git town main-branch [<branch_name>] to view and edit the main branch
    • Added git town non-feature-branches [--add|--remove <branch_name>] to view and modify non-feature branches

    Couple issues:

    • the linter on Travis seems to be different from the one I have. Everything passes locally, but Travis' wants me to fix line 42 of shell_helpers.sh. Following their suggestion, the functionality seems to change and break.
    • The git town "option parsing" seems messy -- any advice?
    • Don't really like the differences between the flags and "subcommands", e.g. git town main-branch vs. git town --config. Would git town config be better than git town --config (per Kevin's original suggestion)?
  • Skip unnecessary pushes

    Skip unnecessary pushes

    @charlierudolph this implements #66.

    This also refactors create_commits in order to allow the same commit to exist locally and remote in feature specs. That wasn't possible before, and is required now.

  • Clarification on child feature workflow

    Clarification on child feature workflow

    I'm trying to understand how parent/child branches work within git-town, but the documentation is a bit confusing.

    There's a comment here indicating that you can't ship a child:

    Only shipping of direct children of the main branch is allowed. To ship a nested child branch, all ancestor branches have to be shipped or killed.

    So, what is the proposed workflow for child branches? Given a feature tree which looks like this:

    Feature A
    └── Feature B
        ├── Feature C
        └── Feature D
    
    

    I would assume that

    • Feature B would be dependent on C and D for completion
    • C and D would be merged into B as they were completed, and
    • B would be merged back into A when it was done.

    Given that you can't ship B, C, or D into their parent branches, is there an official workflow from Town for this use-case, or should I just use standard git commands to issue merges? It's fairly easy to issue pull requests for the features and merge via github after code review, but I have read elsewhere that Town prefers you to not use github's merge and instead use ship, so this seems a bit counter-intuitive and I'm assuming I'm just missing something obvous.

  • group the branch methods in src/config/config.go into better groups

    group the branch methods in src/config/config.go into better groups

    Create these possible structs inside src/config/config.go:

    • branch ancestry
    • perennial branches

    Expected usage:

    config.parentBranches.set()
    config.perennialBranches.add(name)
    config.perennialBranches.remove(name)
    
  • Incrementally update heavily outdated branches

    Incrementally update heavily outdated branches

    why is this needed

    Updating such heavily outdated branches in one step often results in unnecessary merge conflicts because the foundation on which the changes in the branch have been made has changed significantly over time.

    approach

    This problem could be alleviated by updating the outdated branch one commit at a time.

    git sync --incremental
    

    Alternative 1: using Merge Commits

    • start at the common ancestor commit between the main development branch and the feature branch
    • merge the next commit from the main development branch
    • if there are merge conflicts, resolve them
    • commit, or at least stage the changes
    • your branch is now one commit less outdated
    • repeat with the next commit from the main development branch

    Alternative 2: using rebasing

    • organize the commits in your branch so that this becomes easier/faster. Ideally you end up with one commit on your branch, but it could also be a series of single-responsibility commits.
    • start at the common ancestor commit between the main development branch and the feature branch
    • rebase against the next commit from the main development branch
    • if there are merge commits, resolve them
    • finish the rebase
    • your branch is now one commit less outdated
    • repeat with the next commit from the main development branch

    Rebasing seems the cleaner alternative here, this actually seems like a legit use case for rebasing. Rebasing might not always be possible, for example when the branch is shared between multiple repos (and we can't change Git history as a result) or when the branch contains lots of merge commits already.

    benefits

    This gives Git many smaller merge conflicts (which it can resolve automatically) instead of one big conflict (which it can not resolve automatically). Hopefully, this leads to the capability to update heavily outdated branches with less need for humans

    challenges

    A downside of this approach is that it is more complicated and has a learning curve. When using the "Merge Commits" strategy, it can also lead to many merge commits in your feature branch.

  • support for repos on the hosted gitlab.com offering does not work

    support for repos on the hosted gitlab.com offering does not work

    steps to reproduce:

    • set the Git remote to [email protected]:gitlab-com/www-gitlab-com.git
    • run git new-pull-request

    expected behavior: it opens the merge request page for GitLab actual behavior: error message

    Error: unsupported hosting service
    
    This command requires hosting on one of these services:
    * Bitbucket
    * GitHub
    * GitLab
    * Gitea
    
Caddy-git - Git Plugin for Caddy v2

caddy-git Git Plugin for Caddy v2. Inspired by this comment. Please ask question

Jan 1, 2023
one simple git ssh server (just for learning git over ssh )

wriet one simple git ssh server use golang write one simple git ssh server how to running starting service docker-compose up -d add authorized_keys i

Mar 5, 2022
Package socket provides a low-level network connection type which integrates with Go's runtime network poller to provide asynchronous I/O and deadline support. MIT Licensed.

socket Package socket provides a low-level network connection type which integrates with Go's runtime network poller to provide asynchronous I/O and d

Dec 14, 2022
🚀Gev is a lightweight, fast non-blocking TCP network library based on Reactor mode. Support custom protocols to quickly and easily build high-performance servers.
🚀Gev is a lightweight, fast non-blocking TCP network library based on Reactor mode. Support custom protocols to quickly and easily build high-performance servers.

gev 中文 | English gev is a lightweight, fast non-blocking TCP network library based on Reactor mode. Support custom protocols to quickly and easily bui

Jan 6, 2023
High-performance, non-blocking, event-driven, easy-to-use networking framework written in Go, support tls/http1.x/websocket.

High-performance, non-blocking, event-driven, easy-to-use networking framework written in Go, support tls/http1.x/websocket.

Jan 8, 2023
rconn is a multiplatform program for creating generic reverse connections. Lets you consume services that are behind firewall or NAT without opening ports or port-forwarding.
rconn is a multiplatform program for creating generic reverse connections. Lets you consume services that are behind firewall or NAT without opening ports or port-forwarding.

rconn (r[everse] conn[ection]) is a multiplatform program for creating reverse connections. It lets you consume services that are behind NAT and/or fi

Jan 1, 2023
A go module supply Java-Like generic stream programming (while do type check at runtime)

gostream A go module supplying Java-Like generic stream programming (while do type check at runtime) Using Get a Stream To get a Stream, using SliceSt

Jan 16, 2022
Gcra - Package gcra implements the generic cell rate algorithm

gcra Package gcra implements the generic cell rate algorithm (GCRA). Example opt

Jan 23, 2022
Useful collection functions for golang, based on generic types

go-collection English | 简体中文 go-collection provides developers with a convenient set of functions for working with common slices, maps, and arrays dat

Jul 21, 2022
Package raw enables reading and writing data at the device driver level for a network interface. MIT Licensed.

raw Package raw enables reading and writing data at the device driver level for a network interface. MIT Licensed. For more information about using ra

Dec 28, 2022
A tool get level of subdomain from 1....n

dlevel Get any level of subdomain from 1....N Install go get -u github.com/MPaandeey/dlevel Usage Example ?? files.txt hackerone.com info.hackerone.co

Jul 6, 2022
Toy application level encryption protocol

noodle A toy application level encryption module. A a high level, it provides co

Jan 3, 2022
TLDs finder: check domain name availability across all valid top-level domains

TLD:er TLDs finder — check domain name availability across all valid top-level d

Oct 31, 2022
Simple and lightweight SSH git hosting with just a directory.

go-gitdir This project makes it incredibly easy to host a secure git server with a config that can be easily rolled back. It aims to solve a number of

Dec 20, 2022
Extended ssh-agent which supports git commit signing over ssh

ssh-agentx ssh-agentx Rationale Requirements Configuration ssh-agentx Configuration ssh-gpg-signer Linux Windows Signing commits after configuration T

Jun 29, 2022
Switch git user easily with ssh identity.
Switch git user easily with ssh identity.

gitusr A cli tool to easily manage multiple git users and their ssh identity. Add a new git user to gitusr config. Delete a git user from gitusr confi

Aug 22, 2021
gh is GitHub on the command line. It brings pull requests, issues, and other GitHub concepts to the terminal next to where you are already working with git and your code
gh is GitHub on the command line. It brings pull requests, issues, and other GitHub concepts to the terminal next to where you are already working with git and your code

gh is GitHub on the command line. It brings pull requests, issues, and other GitHub concepts to the terminal next to where you are already working with git and your code

Jan 24, 2022
Fast HTTP package for Go. Tuned for high performance. Zero memory allocations in hot paths. Up to 10x faster than net/http
Fast HTTP package for Go. Tuned for high performance. Zero memory allocations in hot paths. Up to 10x faster than net/http

fasthttp Fast HTTP implementation for Go. Currently fasthttp is successfully used by VertaMedia in a production serving up to 200K rps from more than

Jan 5, 2023
High performance async-io(proactor) networking for Golang。golangのための高性能非同期io(proactor)ネットワーキング
High performance async-io(proactor) networking for Golang。golangのための高性能非同期io(proactor)ネットワーキング

gaio Introduction 中文介绍 For a typical golang network program, you would first conn := lis.Accept() to get a connection and go func(net.Conn) to start a

Dec 29, 2022