git-gamble
Craft Your Code,
Step by Step
def hello():
return 'Hello word'
def test_say_hello_world():
assert hello() == 'Hello world'
Are you ready to gamble ?
Pass 🟢
You did :
git-gamble --pass
Your gamble was good :
Committed
Fail 🔴
You did :
git-gamble --fail
But there was a typo :
def hello():
- return 'Hello word'
+ return 'Hello world'
Your gamble was wrong :
Reverted
git-gamble
Craft Your Code, Step by Step !
git-gamble is a tool that blends TDD + TCR to make sure to develop the right thing 😌, baby step by baby step 👶🦶
The release notes will be posted at each version
Created the 2019-12-07
The release notes will be posted at each version
Follow on your preferred social media :
Follow with your preferred format :
Alternatively : you can watch the slides about the theory
TDD (Test Driven Development) is cool!
It makes sure we develop the right thing, step by step
flowchart TB
start([Start])
==> red([Write only 1 failing test])
==> green([Make all tests pass])
==> refactor([Refactor])
==> finish([Finish])
refactor -.->|Incomplete ?| red
classDef red_phase font-weight:bold,color:black,fill:coral;
class red red_phase
classDef green_phase font-weight:bold,color:black,fill:#1cba1c;
class green green_phase
classDef refactor_phase font-weight:bold,color:black,fill:#668cff;
class refactor refactor_phase
Write only 1 failing test
Make all tests pass
Refactor
Repeat while it’s incomplete
Until finish
flowchart TB
subgraph red[Red]
direction LR
fix_layout(( )) ==> write_a_test
write_a_test[Write only 1 failing test]
==> run_tests{{Run tests}}
run_tests
-.->|Pass\nWrite another test| write_a_test
end
start([Start]) === fix_layout
run_tests ==>|Fail| green([Green])
classDef red_phase font-weight:bold,color:black,fill:coral;
class red red_phase
classDef green_phase font-weight:bold,color:black,fill:#1cba1c;
class green green_phase
classDef refactor_phase font-weight:bold,color:black,fill:#668cff;
class refactor refactor_phase
classDef fix_layout stroke:white,fill:transparent;
class fix_layout fix_layout
Write only 1 failing test
Run tests
If the tests pass then
write another test
Else if the tests fail then
go to the green step
flowchart TB
subgraph green[Green]
direction LR
fix_layout(( )) ==> write_the_minimum_code
write_the_minimum_code[Write the minimum code\nto make all tests pass]
==> run_tests{{Run tests}}
run_tests
-.->|Fail\nTry something else| write_the_minimum_code
end
red([Red]) === fix_layout
run_tests ==>|Pass| refactor([Refactor])
classDef red_phase font-weight:bold,color:black,fill:coral;
class red red_phase
classDef green_phase font-weight:bold,color:black,fill:#1cba1c;
class green green_phase
classDef refactor_phase font-weight:bold,color:black,fill:#668cff;
class refactor refactor_phase
classDef fix_layout stroke:white,fill:transparent;
class fix_layout fix_layout
Write the minimum code to make all tests pass
Run tests
If the tests fail then
try something else
Else if the tests pass then
go to the refactor step
flowchart TB
subgraph refactor[Refactor]
direction LR
rewrite_code[Rewrite code\nwithout changing the behaviour]
==> run_tests{{Run tests}}
-.->|Pass\nAnother things to refactor ?| rewrite_code
run_tests
-->|Fail\nChange something else| rewrite_code
end
green([Green]) ==> rewrite_code
run_tests ==>|Pass| finish([Finish])
run_tests -.->|Pass\nAnother feature to add ?| red([Red])
classDef red_phase font-weight:bold,color:black,fill:coral;
class red red_phase
classDef green_phase font-weight:bold,color:black,fill:#1cba1c;
class green green_phase
classDef refactor_phase font-weight:bold,color:black,fill:#668cff;
class refactor refactor_phase
classDef fix_layout stroke:white,fill:transparent;
class fix_layout fix_layout
Rewrite code without changing the behaviour
Run tests
If the tests fail then
change something else and repeat the refactor step
Else if the tests pass and
there are another things to refactor then
repeat the refactor step
there is another feature to add then
go to the red step
there nothing else to do then
it’s finished
TCR (test && commit || revert) is cool!
It encourages doing baby steps , reducing the waste when we are wrong
flowchart TB
gamble{{Gambling on test results}}
gamble ==>|Pass| commit(Commit)
gamble -->|Fail| revert(Revert)
Gambling on test results
If the tests pass then
commit
If the tests fail then
revert
flowchart TB
start([Start])
==> green([Change some code])
==> finish([Finish])
green -.->|Incomplete ?| green
classDef green_phase font-weight:bold,color:black,fill:#1cba1c;
class green green_phase
Change some code
Repeat while it’s incomplete
Until finish
But it doesn’t allow us to see the tests failing
So:
Maybe we test nothing (assert forgotten)
def test_should_be_Buzz_given_5():
input = 5
actual = fizz_buzz(input)
# Oops! Assert has been forgotten
Maybe we are testing something that is not the thing we should be testing
it("should be Fizz given 3", () => {
const input = 3;
const actual = fizzBuzz(input);
expect(input).toBe("Fizz");
// Oops! Asserts on the input value instead of the actual value
});
flowchart TB
subgraph green[Green]
direction TB
start([Start])
==> change_code[Change some code]
==> run_tests{{"Run tests\n<code>test && commit || revert</code>"}}
==>|Pass| commit(Commit)
==> finish([Finish])
commit
-->|Another things to change ?| change_code
run_tests
-.->|Fail| revert(Revert)
-.->|Try something else| change_code
end
classDef green_phase font-weight:bold,color:black,fill:#1cba1c;
class green green_phase
Change some code
Run teststest && commit || revert
If the tests fail then
Revert
Try something else
Repeat
If the tests pass then
Commit
If there are another things to change then
repeat
If there is nothing else to do then
it’s finished
venn-beta
set TCR
set TDD
union TCR,TDD["TCRDD"]
T CRDD = T CR + T DD
TCRDD blends the constraints of the two methods
to benefit from their advantages
Therefore,
TCRDD makes sure we develop the right thing,
step by step,
and we are encouraged to do so by baby steps ,
reducing the waste when we are wrong
flowchart TB
red{{Write only 1 failing test}}
green{{Make all tests pass}}
refactor{{Refactor}}
red ~~~ red_commit
green ~~~ green_commit
refactor ~~~ refactor_commit
red ==>|Fail| red_commit(Commit) ==> green
green ==>|Pass| green_commit(Commit) ==> refactor
refactor ==>|Pass| refactor_commit(Commit)
red -->|Pass| red_revert(Revert) --> red
green -->|Fail| green_revert(Revert) --> green
refactor -->|Fail| refactor_revert(Revert) --> refactor
red_revert ~~~ green
green_revert ~~~ refactor
classDef red_phase font-weight:bold,color:black,fill:coral;
class red red_phase
classDef green_phase font-weight:bold,color:black,fill:#1cba1c;
class green green_phase
classDef refactor_phase font-weight:bold,color:black,fill:#668cff;
class refactor refactor_phase
Red phase
Write only 1 failing test
If the tests pass then
Revert
Retry the red phase
Else if the tests fail then
Commit
Go to the green phase
Green phase
Make all tests pass
If the tests fail then
Revert
Retry the green phase
Else if the tests pass then
Commit
Go to the refactor phase
Refactor phase
Refactor
If the tests fail then
Revert
Retry the refactor phase
Else if the tests pass then
Commit
flowchart TB
subgraph red[Red]
direction LR
fix_layout(( )) ==> write_a_test
write_a_test[Write only 1 test]
==> gamble[/Gamble that the test fail\n<code>git gamble --red</code>/]
==> run_tests{{Actually run tests}}
==>|Fail| commit(Commit)
run_tests
-->|Pass| revert(Revert)
-->|Write another test| write_a_test
end
start([Start]) ==> fix_layout
commit ==> green([Green])
classDef red_phase font-weight:bold,color:black,fill:coral;
class red red_phase
classDef green_phase font-weight:bold,color:black,fill:#1cba1c;
class green green_phase
classDef refactor_phase font-weight:bold,color:black,fill:#668cff;
class refactor refactor_phase
classDef fix_layout stroke:white,fill:transparent;
class fix_layout fix_layout
Write only 1 test
Gamble that the test failgit gamble --red
Actually run tests
If the tests pass then
Revert
Write another test
Else if the tests fail then
Commit
Go to the green phase
flowchart TB
subgraph green[Green]
direction LR
fix_layout(( )) ==> write_the_minimum_code
write_the_minimum_code[Write the minimum code]
==> gamble[/Gamble that the tests pass\n<code>git gamble --green</code>/]
==> run_tests{{Actually run tests}}
==>|Pass| commit(Commit)
run_tests
-->|Fail| revert(Revert)
-->|Try something else| write_the_minimum_code
end
red([Red]) ==> fix_layout
commit ==> refactor([Refactor])
classDef red_phase font-weight:bold,color:black,fill:coral;
class red red_phase
classDef green_phase font-weight:bold,color:black,fill:#1cba1c;
class green green_phase
classDef refactor_phase font-weight:bold,color:black,fill:#668cff;
class refactor refactor_phase
classDef fix_layout stroke:white,fill:transparent;
class fix_layout fix_layout
Write the minimum code
Gamble that the tests passgit gamble --green
Actually run tests
If the tests fail then
Revert
Try something else
Else if the tests pass then
Commit
Go to the refactor phase
flowchart TB
subgraph refactor[Refactor]
direction LR
rewrite_code[Rewrite code\nwithout changing the behaviour]
==> gamble[/Gamble that the tests pass\n<code>git gamble --refactor</code>/]
==> run_tests{{Actually run tests}}
==>|Pass| commit(Commit)
-.->|Another things to refactor ?| rewrite_code
run_tests
-->|Fail| revert(Revert)
-->|Change something else| rewrite_code
end
green([Green]) ==> rewrite_code
commit ==> finish([Finish])
commit -.->|Another feature to add ?| red([Red])
classDef red_phase font-weight:bold,color:black,fill:coral;
class red red_phase
classDef green_phase font-weight:bold,color:black,fill:#1cba1c;
class green green_phase
classDef refactor_phase font-weight:bold,color:black,fill:#668cff;
class refactor refactor_phase
classDef fix_layout stroke:white,fill:transparent;
class fix_layout fix_layout
Rewrite code
without changing the behaviour
Gamble that the tests passgit gamble --refactor
Actually run tests
If the tests fail then
Revert
Change something else
Else if the tests pass then
Commit
If there are another things to refactor then
go to the refactor phase
Else if there is another feature to add then
go to the red phase
Else if there is nothing else to do then
it’s finished
git-gamble is a tool that helps to use the TCRDD method
Some pages of this documentation can be watched as slides presentation
You can watch the slides about why baby steps are important
You can watch the slides about what is the theory
You can watch the slides to learn how to work with it
timeline
title History of TCRDD
2018
: TCR `test && commit || revert` Article by Kent Beck 2018-09-28
: TCRDD _TDD is dead, long live TCR?_ Article by Xavier Detant 2018-12-03
2019
: Xavier's TCRDD First commit 2019-08-26
: git-gamble First commit 2019-12-07
2021 : Murex's TCR First commit 2021-06-16
2025 : git-bet's TCRDD First commit 2025-10-26
Why reinvent the wheel?
The script of Xavier Detant already works well
Because i would like to learn Rust ¯\_(ツ)_/¯
The package is available on these repositories , and can be installed as usual if you use one of them
There are several methods to install depending on your operating system:
Installation is currently not really convenient, so contributions are welcome
Feel free to add package to your favourite package repository
Nix is a package manager available for Linux, macOS and Windows (through WSL2)
Install Nix
Check the installation with this command :
nix --version
If it has been well settled , it should output something like this :
nix (Nix) 2.22.3
Else if it has been badly settled , it should output something like this :
nix: command not found
The package is available on nixpkgs
nix-shell --packages git-gamble
Check if all have been well settled :
git gamble --version
If it has been well settled , it should output this :
git-gamble 2.14.6
Else if it has been badly settled , it should output this :
git : 'gamble' is not a git command. See 'git --help'.
Note: the latest version, not yet released, is also available
Use without installing :
export NIX_CONFIG="extra-experimental-features = flakes nix-command"
nix run gitlab:pinage404/git-gamble -- --help
To install it at project level with flake.nix, see example
export NIX_CONFIG="extra-experimental-features = flakes nix-command"
nix flake init --template gitlab:pinage404/git-gamble
To automate the setup of the environment it’s recommended to install DirEnv
Then run this command :
direnv allow
To avoid rebuilding from scratch, Cachix can be used
cachix use git-gamble
export NIX_CONFIG="extra-experimental-features = flakes nix-command"
nix flake update
It should work on any Debian based distributions : Linux Mint , Ubuntu …
git-gamble doesn’t repackage git, it uses the one installed on your system
Install git manually
Make sure it is available in your $PATH , you can check it with this command :
git --version
If it has been well settled , it should output something like this :
git version 2.54.0
Else if it has been badly settled , it should output something like this :
git: command not found
Note : if you are using a very old version of git (below 2.36)
With old git version, git-gamble will fail with this error
git: 'hook' is not a git command. See 'git --help'.
The most similar commands are
fork
lock
root
Failed to execute `git hook run --ignore-missing pre-gamble -- pass` in . returns code 1
The pre-gamble hook returns code 1, but it should be 0
You can test the hook by executing : git hook run --ignore-missing pre-gamble -- pass
No tests have been run, and nothing has been committed or reverted
git 2.36 was released the 2022-04-18, and is now available in most package managers
If you can, try to upgrade git using your package manager
Else, to use git-gamble with git below 2.36, git-gamble’s hooks must be disabled by installing git-gamble with the option to disable the feature
Go to the package registry page
Go to the latest version of git-gamble-debian
Download the latest version git-gamble_2.14.6_amd64.deb
Install package
Execute this command as root :
dpkg --install git-gamble*.deb
Note: the latest version, not yet released, is also available
This is not really convenient, but a better way could come when GitLab Debian Package Manager MVC will be available
Check if all have been well settled :
git gamble --version
If it has been well settled , it should output this :
git-gamble 2.14.6
Else if it has been badly settled , it should output this :
git : 'gamble' is not a git command. See 'git --help'.
There is no update mechanism
Execute this command as root :
dpkg --remove git-gamble
Installation is currently not really convenient, so contributions are welcome
Feel free to add package to your favourite package repository
Install Homebrew
Check the installation with this command :
brew --version
If it has been well settled , it should output something like this :
Homebrew 4.3.14
Homebrew/homebrew-core (git revision 7a574d89134; last commit 2024-08-07)
Else if it has been badly settled , it should output something like this :
brew: command not found
Note : if you are using a very old version of git (below 2.36)
With old git version, git-gamble will fail with this error
git: 'hook' is not a git command. See 'git --help'.
The most similar commands are
fork
lock
root
Failed to execute `git hook run --ignore-missing pre-gamble -- pass` in . returns code 1
The pre-gamble hook returns code 1, but it should be 0
You can test the hook by executing : git hook run --ignore-missing pre-gamble -- pass
No tests have been run, and nothing has been committed or reverted
git 2.36 was released the 2022-04-18, and is now available in most package managers
If you can, try to upgrade git using your package manager
Else, to use git-gamble with git below 2.36, git-gamble’s hooks must be disabled by installing git-gamble with the option to disable the feature
Run these commands :
brew tap pinage404/git-gamble https://gitlab.com/pinage404/git-gamble.git
brew trust pinage404/git-gamble
brew install --HEAD git-gamble
Or add this to the Brewfile :
tap "pinage404/git-gamble", "https://gitlab.com/pinage404/git-gamble.git", trusted: true
brew "pinage404/git-gamble/git-gamble", args: ["HEAD"]
Then run this command :
brew bundle install
Note : it will be a bit long because it will compile the project and download every dependency needed by the compilation ; Check the section to improve installation
Check if all have been well settled :
git gamble --version
If it has been well settled , it should output this :
git-gamble 2.14.6
Else if it has been badly settled , it should output this :
git : 'gamble' is not a git command. See 'git --help'.
git-gamble has not yet been packaged by Homebrew
To upgrade git-gamble, run this command :
brew reinstall git-gamble
brew uninstall git-gamble
brew untap pinage404/git-gamble
Installation is currently not really convenient, so contributions are welcome
Feel free to add package to your favourite package repository
Homebrew requires repositories to have at least 75 stars and 30 forks
So, please add a star on GitLab
and create a fork for any contribution
Install Chocolatey
Check the installation with this command :
choco --version
If it has been well settled , it should output something like this :
2.3.0
Else if it has been badly settled , it should output something like this :
choco: command not found
git-gamble doesn’t repackage git, it uses the one installed on your system
Install git manually
Make sure it is available in your $PATH , you can check it with this command :
git --version
If it has been well settled , it should output something like this :
git version 2.54.0
Else if it has been badly settled , it should output something like this :
git: command not found
Note : if you are using a very old version of git (below 2.36)
With old git version, git-gamble will fail with this error
git: 'hook' is not a git command. See 'git --help'.
The most similar commands are
fork
lock
root
Failed to execute `git hook run --ignore-missing pre-gamble -- pass` in . returns code 1
The pre-gamble hook returns code 1, but it should be 0
You can test the hook by executing : git hook run --ignore-missing pre-gamble -- pass
No tests have been run, and nothing has been committed or reverted
git 2.36 was released the 2022-04-18, and is now available in most package managers
If you can, try to upgrade git using your package manager
Else, to use git-gamble with git below 2.36, git-gamble’s hooks must be disabled by installing git-gamble with the option to disable the feature
Note:
If you installed Chocolatey from an administrative shell,
make sure to launch all choco commands from an administrative shell as well.
Check the version of Chocolatey installed using this command :
choco --version
Chocolatey v2.x
choco source add --name=git-gamble --source="https://gitlab.com/api/v4/projects/15761766/packages/nuget/index.json"
choco install git-gamble.portable
Chocolatey v1.x
Use the Nuget v2 source :
choco source add --name=git-gamble --source="https://gitlab.com/api/v4/projects/15761766/packages/nuget/v2"
choco install git-gamble.portable --version=2.14.6
The Gitlab registry doesn’t seem to fully support package discovery on the v2 source,
so the version needs to be specified explicitly. This issue might address this.
Note: the latest version, not yet released, is also available
Check if all have been well settled :
git gamble --version
If it has been well settled , it should output this :
git-gamble 2.14.6
Else if it has been badly settled , it should output this :
git : 'gamble' is not a git command. See 'git --help'.
choco upgrade git-gamble.portable
With Chocolatey v1.x and/or the Nuget v2 source :
choco upgrade git-gamble.portable --version=2.14.6
choco uninstall git-gamble.portable
You might also want to remove the source :
choco source remove --name=git-gamble
Installation is currently not really convenient, so contributions are welcome
Feel free to add package to your favourite package repository
Install Mise
Check the installation with this command :
mise --version
If it has been well settled , it should output something like this :
_ __
____ ___ (_)_______ ___ ____ ____ / /___ _________
/ __ `__ \/ / ___/ _ \______/ _ \/ __ \______/ __ \/ / __ `/ ___/ _ \
/ / / / / / (__ ) __/_____/ __/ / / /_____/ /_/ / / /_/ / /__/ __/
/_/ /_/ /_/_/____/\___/ \___/_/ /_/ / .___/_/\__,_/\___/\___/
/_/ by @jdx
2026.5.12 linux-x64 (1980-01-01)
mise WARN mise version 2026.6.9 available
Else if it has been badly settled , it should output something like this :
mise: command not found
git-gamble doesn’t repackage git, it uses the one installed on your system
Install git manually
Make sure it is available in your $PATH , you can check it with this command :
git --version
If it has been well settled , it should output something like this :
git version 2.54.0
Else if it has been badly settled , it should output something like this :
git: command not found
Note : if you are using a very old version of git (below 2.36)
With old git version, git-gamble will fail with this error
git: 'hook' is not a git command. See 'git --help'.
The most similar commands are
fork
lock
root
Failed to execute `git hook run --ignore-missing pre-gamble -- pass` in . returns code 1
The pre-gamble hook returns code 1, but it should be 0
You can test the hook by executing : git hook run --ignore-missing pre-gamble -- pass
No tests have been run, and nothing has been committed or reverted
git 2.36 was released the 2022-04-18, and is now available in most package managers
If you can, try to upgrade git using your package manager
Else, to use git-gamble with git below 2.36, git-gamble’s hooks must be disabled by installing git-gamble with the option to disable the feature
Run this command :
mise use gitlab:pinage404/git-gamble
Check if all have been well settled :
git gamble --version
If it has been well settled , it should output this :
git-gamble 2.14.6
Else if it has been badly settled , it should output this :
git : 'gamble' is not a git command. See 'git --help'.
mise upgrade gitlab:pinage404/git-gamble --bump
mise unuse gitlab:pinage404/git-gamble
Installation is currently not really convenient, so contributions are welcome
Feel free to add package to your favourite package repository
Some community projects seem to make available git-gamble to the Scoop ecosystem
⚠️
They are not officially endorsed by git-gamble, there is no warranty, use at your own risk, use them if you trust there respective authors
⚠️
Install Scoop
git-gamble doesn’t repackage git, it uses the one installed on your system
Install git manually
Make sure it is available in your $PATH , you can check it with this command :
git --version
If it has been well settled , it should output something like this :
git version 2.54.0
Else if it has been badly settled , it should output something like this :
git: command not found
Note : if you are using a very old version of git (below 2.36)
With old git version, git-gamble will fail with this error
git: 'hook' is not a git command. See 'git --help'.
The most similar commands are
fork
lock
root
Failed to execute `git hook run --ignore-missing pre-gamble -- pass` in . returns code 1
The pre-gamble hook returns code 1, but it should be 0
You can test the hook by executing : git hook run --ignore-missing pre-gamble -- pass
No tests have been run, and nothing has been committed or reverted
git 2.36 was released the 2022-04-18, and is now available in most package managers
If you can, try to upgrade git using your package manager
Else, to use git-gamble with git below 2.36, git-gamble’s hooks must be disabled by installing git-gamble with the option to disable the feature
Add one of this bucket :
Only add a bucket that you trust
⚠️
Then run these commands :
scoop update
scoop install git-gamble
Check if all have been well settled :
git gamble --version
If it has been well settled , it should output this :
git-gamble 2.14.6
Else if it has been badly settled , it should output this :
git : 'gamble' is not a git command. See 'git --help'.
It’s probably possible ; Check the section to improve installation
It’s probably possible ; Check the section to improve installation
Installation is currently not really convenient, so contributions are welcome
Feel free to add package to your favourite package repository
If you use Scoop, your help is wanted to improve this page
Install Cargo
Check the installation with this command :
cargo --version
If it has been well settled , it should output something like this :
cargo 1.80.0 (376290515 2024-07-16)
Else if it has been badly settled , it should output something like this :
cargo: command not found
git-gamble doesn’t repackage git, it uses the one installed on your system
Install git manually
Make sure it is available in your $PATH , you can check it with this command :
git --version
If it has been well settled , it should output something like this :
git version 2.54.0
Else if it has been badly settled , it should output something like this :
git: command not found
Note : if you are using a very old version of git (below 2.36)
With old git version, git-gamble will fail with this error
git: 'hook' is not a git command. See 'git --help'.
The most similar commands are
fork
lock
root
Failed to execute `git hook run --ignore-missing pre-gamble -- pass` in . returns code 1
The pre-gamble hook returns code 1, but it should be 0
You can test the hook by executing : git hook run --ignore-missing pre-gamble -- pass
No tests have been run, and nothing has been committed or reverted
git 2.36 was released the 2022-04-18, and is now available in most package managers
If you can, try to upgrade git using your package manager
Else, to use git-gamble with git below 2.36, git-gamble’s hooks must be disabled by installing git-gamble with the option to disable the feature
Install binary
Use cargo-binstall to avoid compilation
If binaries are available for your platform
It will download binaries
Else
It will fall back to compilation from source
Run the following command :
cargo binstall git-gamble
If you want to compile from source
Run this command :
cargo install git-gamble
Add ~/.cargo/bin to your $PATH
Cargo have a mechanism to enable or disable features at compile time
By default , git-gamble is compiled with :
To remove these features, install using the following command :
cargo install git-gamble --no-default-features
To enable only one of these features :
with_subcommand_hook (requires and includes with_custom_hooks)
cargo install git-gamble --no-default-features --features "with_subcommand_hook"
with_custom_hooks
cargo install git-gamble --no-default-features --features "with_custom_hooks"
with_subcommand_generate_shell_completions
cargo install git-gamble --no-default-features --features "with_subcommand_generate_shell_completions"
Check if all have been well settled :
git gamble --version
If it has been well settled , it should output this :
git-gamble 2.14.6
Else if it has been badly settled , it should output this :
git : 'gamble' is not a git command. See 'git --help'.
cargo update --package git-gamble
cargo uninstall git-gamble
git-gamble doesn’t repackage git, it uses the one installed on your system
Install git manually
Make sure it is available in your $PATH , you can check it with this command :
git --version
If it has been well settled , it should output something like this :
git version 2.54.0
Else if it has been badly settled , it should output something like this :
git: command not found
Note : if you are using a very old version of git (below 2.36)
With old git version, git-gamble will fail with this error
git: 'hook' is not a git command. See 'git --help'.
The most similar commands are
fork
lock
root
Failed to execute `git hook run --ignore-missing pre-gamble -- pass` in . returns code 1
The pre-gamble hook returns code 1, but it should be 0
You can test the hook by executing : git hook run --ignore-missing pre-gamble -- pass
No tests have been run, and nothing has been committed or reverted
git 2.36 was released the 2022-04-18, and is now available in most package managers
If you can, try to upgrade git using your package manager
Else, to use git-gamble with git below 2.36, git-gamble’s hooks must be disabled by installing git-gamble with the option to disable the feature
Only for Linux and Windows x86_64 :
Download the binary on the release page
Rename it to git-gamble
Put it in your $PATH
Note : the latest version, not yet released, is also available :
Check if all have been well settled :
git gamble --version
If it has been well settled , it should output this :
git-gamble 2.14.6
Else if it has been badly settled , it should output this :
git : 'gamble' is not a git command. See 'git --help'.
There is no update mechanism
Just remove the binary from your $PATH
git-gamble works with all languages and tools and editors
To see all available flags and options
git gamble --help
Dash - between git and gamble may be only needed for --help
git-gamble --help
There are two ways to run your tests using git-gamble :
In both cases,
the test command must exit with a 0 status when there are 0 failed tests,
anything else is considered as a failure
Setting an environment variable and run only the git gamble command
Start by setting an environment variable with the test command :
The example below is for running your tests for a Rust project
export GAMBLE_TEST_COMMAND="cargo test"
Use the appropriate command for your shell :
Write a failing test in your codebase, then :
git gamble --red
# or
git gamble --fail
Write the minimum code to make tests pass, then :
git gamble --green
# or
git gamble --pass
Refactor your code, then :
git gamble --refactor
# or
git gamble --pass
To avoid re-exporting manually the variable at each new terminal, it’s recommended to install DirEnv
Then add in a .envrc file
export GAMBLE_TEST_COMMAND="cargo test"
Then run this command
direnv allow
Typing the git gamble command with your test command repetitively
Write a failing test in your codebase, then :
git gamble --red -- $YOUR_TEST_COMMAND
The example below is for running your tests for a Node.js project that use PNPM
git gamble --red -- pnpm test
Write the minimum code to make tests pass, then :
git gamble --green -- $YOUR_TEST_COMMAND
Refactor your code, then :
git gamble --refactor -- $YOUR_TEST_COMMAND
For more detailed example, view the demo
git-gamble’s demo to develop using TCRDD by doing baby steps
On a simple program
git-gamble works with all languages and tools and editor ;
this example uses python with pytest and nano
export GAMBLE_TEST_COMMAND='pytest --quiet'
Note : for a simpler demo, test code and production code are in the same file
Alternatively : you can also watch the slides about the demo
Write a program that says Hello world
Asciinema
Alternative text
nano test_hello.py
def hello():
pass
def test_say_hello_world():
assert hello() == 'Hello world'
Then, gamble that the tests fail
git gamble --red
Committed
Let’s fake it
Asciinema
Alternative text
nano test_hello.py
def hello():
return 'Hello word'
Then, gamble that the tests pass
git gamble --green
Reverted
Oh ! No !
I made a typo
def hello():
- return 'Hello word'
+ return 'Hello world'
Try again
Let’s fake it without typo
Asciinema
Alternative text
nano test_hello.py
def hello():
return 'Hello world'
Gamble again that the tests pass
git gamble --green
Committed
Yeah !
Then 🔁 Repeat ➰
Write a program that says Hello to the given name when a name is given
Asciinema
Alternative text
nano test_hello.py
def test_say_hello_name_given_a_name():
assert hello('Jon') == 'Hello Jon'
git gamble --red
Committed
Add a simple condition to handle both cases
Asciinema
Alternative text
nano test_hello.py
def hello(arg=None):
if arg:
return f'Hello {arg}'
return 'Hello world'
git gamble --green
Committed
It can be simplified
Asciinema
Alternative text
nano test_hello.py
def hello(arg='world'):
return f'Hello {arg}'
git gamble --refactor
Committed
Better naming
Asciinema
Alternative text
nano test_hello.py
def hello(name='world'):
return f'Hello {name}'
git gamble --refactor
Committed
And so on… ➿
🔁 Repeat until you have tested all the rules, are satisfied and enough confident
git gamble --help
Blend TDD (Test Driven Development) + TCR (`test && commit || revert`) to make sure to develop
the right thing 😌, baby step by baby step 👶🦶
Usage: git-gamble [OPTIONS] <--pass|--fail> -- <TEST_COMMAND>...
git-gamble [OPTIONS] <COMMAND>
Commands:
generate-shell-completions
hook Help to use samples hooks
help Print this message or the help of the given subcommand(s)
Arguments:
<TEST_COMMAND>... The command to execute to know the result [env: GAMBLE_TEST_COMMAND=]
Options:
-g, --pass Gamble that tests should pass [aliases: --green, --refactor]
-r, --fail Gamble that tests should fail [aliases: --red]
-n, --dry-run Do not make any changes and run test command
--no-verify Do not run git hooks
-C, --repository-path <REPOSITORY_PATH> Repository path [default: .]
-m, --message <MESSAGE> Commit's message [default: ""]
-e, --edit Open editor to edit commit's message
--fixup <FIXUP> Fixes up commit
--squash <SQUASH> Construct a commit message for use with `rebase --autosquash`
-h, --help Print help
-V, --version Print version
Any contributions (feedback, bug report, merge request ...) are welcome
https://git-gamble.is-cool.dev/contributing/index.html
To manually generate shell completions, use this command :
git gamble generate-shell-completions --help
Usage: git-gamble generate-shell-completions [SHELL]
Arguments:
[SHELL]
Put generated file here :
* Bash : add it to your bash profile in ~/.bashrc
* Fish : see https://fishshell.com/docs/current/completions.html#where-to-put-completions
* Powershell : see https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_profiles
* Others shells : don't know, MR are welcome
[possible values: bash, elvish, fish, powershell, zsh]
Options:
-h, --help
Print help (see a summary with '-h')
To use examples hooks , use this command :
git gamble hook --help
Help to use samples hooks
Usage: git-gamble hook <COMMAND>
Commands:
enable Enable a sample hook
disable Disable a sample hook
help Print this message or the help of the given subcommand(s)
Options:
-h, --help Print help
Require git 2.54.0 or higher to actually execute hooks
With git 2.53.0 or below, you have to manually setup hooks
https://git-gamble.is-cool.dev/usage/hooks/examples.html#using-with-git-2530-or-below
The available hooks are just examples
Create any others behaviors using hooks using the standard git hook API
https://git-scm.com/docs/git-hook
To have more informations, read the documentation about hooks
https://git-gamble.is-cool.dev/usage/hooks.html
There are several examples with several languages in the nix-sandboxes repository
In each language folder, there is a .envrc file, which contains the variable GAMBLE_TEST_COMMAND , that mainly refers to mask commands that are described in the sibling file maskfile.md
(The links above link to the Rust sandbox just for example )
These are only examples, the tool should work with any languages and tools
Install watchexec , then :
watchexec -- git gamble --refactor
This is just TCR (without TDD )
Some examples of git alias
~/.gitconfig or .git/config
[alias]
# git-gamble aliases
fail = gamble --fail
pass = gamble --pass
faile = gamble --fail --edit
passe = gamble --pass --edit
# git-gamble TDD's aliases
red = gamble --red
green = gamble --green
refactor = gamble --refactor
rede = gamble --red --edit
If you use Fish Shell , it works very well with the plugin enlarge_your_git_alias
git-gamble provides his own custom git hooks to enhance the development workflow
These hooks can be used to perform specific actions before and after gambling
The pre-gamble hook is executed before the actual gambling process begins
Sometimes, you want to have certain things imperatively done before gambling on the tests
What if something irrelevant was just missing and that forgetting this was not worth starting again ?
Examples :
The post-gamble hook is triggered after the gambling result is known
Sometimes, you want to do actions after the gamble only in some situations
Examples :
Wrong gamble (pass fail or fail pass)
Good gamble (pass pass or fail fail)
Failing tests (fail fail)
Remember to not push on the main branch
Passing tests (pass pass)
See more usable examples
If you have more ideas, please share them by opening an issue
Custom hooks are called with arguments :
pre-gamble <GAMBLED>
pre-gamble hook is executed with one argument <GAMBLED>
post-gamble <GAMBLED> <ACTUAL>
post-gamble hook is executed with two arguments <GAMBLED> and <ACTUAL>
Where :
<GAMBLED> is pass or fail
<ACTUAL> is pass or fail
Custom hooks of git-gamble are like any other client-side git hooks :
a hook is a file (pre-gamble or post-gamble)
a hook must be in the $GIT_DIR/hooks/ folder
or in the folder configured by git config core.hooksPath
a hook must be executable
will not be executed if any of these options are used :
The following diagram shows when custom hooks are executed in relation to standard git hooks
flowchart LR
subgraph git-gamble's hooks' lifecycle
direction TB
git-gamble([git-gamble --pass\nOR\ngit-gamble --fail])
--> pre-gamble[pre-gamble pass\nOR\npre-gamble fail]:::gitGambleHookStyle
--> git_add([git add --all]):::gitGambleInternalStyle
--> GAMBLE_TEST_COMMAND([exec $GAMBLE_TEST_COMMAND]):::gitGambleInternalStyle
--> gamble{Gamble result ?}:::gitGambleInternalStyle
gamble -->|Gamble success| Success
subgraph Success
direction TB
git_commit([git commit]):::gitGambleInternalStyle
--> pre-commit:::gitHookStyle
--> prepare-commit-msg[prepare-commit-msg\n$GIT_DIR/COMMIT_EDITMSG\nmessage]:::gitHookStyle
--> commit-msg[commit-msg\n$GIT_DIR/COMMIT_EDITMSG]:::gitHookStyle
--> post-commit:::gitHookStyle
post-commit --> rewritten?
rewritten?{{"Last commit rewritten ?\nWhen gambling fail\nafter another gamble fail"}}:::gitGambleInternalStyle
rewritten? -->|Yes| post-rewrite[post-rewrite\namend]:::gitHookStyle --> post-gamble-success
rewritten? -->|No| post-gamble-success
post-gamble-success[post-gamble pass pass\nOR\npost-gamble fail pass]:::gitGambleHookStyle
end
gamble -->|Gamble error| Error
subgraph Error
direction TB
git_reset([git reset --hard]):::gitGambleInternalStyle
--> post-gamble-error[post-gamble pass fail\nOR\npost-gamble fail fail]:::gitGambleHookStyle
end
end
subgraph Legend
direction TB
subgraph Legend_[" "]
direction LR
command([Command executed\nby user])
git-gamble_command([Command executed\nby git-gamble]):::gitGambleInternalStyle
condition{Condition ?}:::gitGambleInternalStyle
end
subgraph Hooks
direction LR
hook[git's hook]:::gitHookStyle
hook_with_argument[git's hook\nfirst_argument\nsecond_argument]:::gitHookStyle
git-gamble_hook_with_argument[git-gamble's hook\nfirst_argument\nsecond_argument]:::gitGambleHookStyle
end
end
classDef gitHookStyle fill:#f05133,color:black,stroke:black;
classDef gitGambleHookStyle fill:#5a3730,color:white,stroke:white;
classDef gitGambleInternalStyle fill:#411d16,color:white,stroke:white;
Textual description of the hooks execution lifecycle
User executes the command git-gamble --pass OR git-gamble --fail
git-gamble executes the hook pre-gamble pass OR pre-gamble fail
git-gamble executes the command git add --all
git-gamble executes the command exec $GAMBLE_TEST_COMMAND
When gamble success
git-gamble executes the command git commit
git executes the hook pre-commit
git executes the hook prepare-commit-msg $GIT_DIR/COMMIT_EDITMSG message
git executes the hook commit-msg $GIT_DIR/COMMIT_EDITMSG
git executes the hook post-commit
When gambling fail after another gamble fail
git executes the hook post-rewrite amend
git-gamble executes the hook post-gamble pass pass OR post-gamble fail pass depending on what the user gambled
When gamble error
git-gamble executes the command git reset --hard
git-gamble executes the hook post-gamble pass fail OR post-gamble fail fail depending on what the user gambled
If you have more ideas, please share them by opening an issue
A simple assistant that displays tips based on the result of the gamble
With git 2.54.0 or higher, use this hook with this command :
git gamble hook enable assistant
With git 2.53.0 or below, download the file
(post-gamble.assistant.sample.sh )
and follow these steps
Specially adapted to near real-time collaboration by pushing when tests pass
With git 2.54.0 or higher, use this hook with this command :
git gamble hook enable real-time-collaboration
With git 2.53.0 or below, download the file
(post-gamble.real-time-collaboration.sample.sh )
and follow these steps
If you are using git-time-keeper , these hooks start and stop the time-keeper between gambling
With git 2.54.0 or higher, use this hook with this command :
git gamble hook enable time-keeper
With git 2.53.0 or below, download the following files
and follow these steps
A hook that plays a random sound based on the result of the gamble
The example uses sound samples from the French series Kaamelott
With git 2.54.0 or higher, use this hook with this command :
git gamble hook enable sound
With git 2.53.0 or below, download the file
(post-gamble.sound.sample.sh )
and follow these steps
If you want more sounds,
set the environment variable KAAMELOTT_FAN=1
but beware, many are vulgar and can upset the most sensitive people
To play the sound using FFMPEG instead of VLC
set the variable PLAY_COMMAND="ffplay -v 0 -nodisp -autoexit"
Any command that accepts an HTTP URL to a MP3 should work
Download the files
Get the hooks’ path :
the path configured by git config set core.hooksPath <PATH>
.git/hooks/ folder by default
HOOKS_PATH="$(git config get core.hooksPath || echo "${GIT_DIR:-.git}/hooks")"
Move the files to your project in the hooks’ path
Concatenate the files in a single one and rename to pre-gamble or post-gamble :
To use several examples, the files must be concatenated
cat "$HOOKS_PATH"/pre-gamble.*.sample.sh >"$HOOKS_PATH"/pre-gamble
cat "$HOOKS_PATH"/post-gamble.*.sample.sh >"$HOOKS_PATH"/post-gamble
Make them executable :
chmod +x "$HOOKS_PATH"/{pre,post}-gamble
Note : with git 2.53.0 or below, the following command will work, but the hook won’t execute
git gamble hook enable <HOOK>
To remove the hook, just remove the file
To run git-gamble from VSCode
Add this in your .vscode/tasks.json
{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "2.0.0",
"tasks": [
{
"label": "Gamble fail",
"type": "shell",
"command": "direnv exec . git gamble --fail",
"group": "test",
},
{
"label": "Gamble pass",
"type": "shell",
"command": "direnv exec . git gamble --pass",
"group": "test",
},
{
"label": "Gamble red",
"type": "shell",
"command": "direnv exec . git gamble --red",
"group": "test",
},
{
"label": "Gamble green",
"type": "shell",
"command": "direnv exec . git gamble --green",
"group": "test",
},
{
"label": "Gamble refactor",
"type": "shell",
"command": "direnv exec . git gamble --refactor",
"group": "test",
},
]
}
Remove direnv exec . if you don’t use DirEnv yet
Open the Command Palette (F1 or CTRL + Shift + P )
Select Tasks: Run Task
Select the task (e.g. Gamble refactor)
You can bind keyboard shortcuts
For example
[
{
"key": "ctrl+g ctrl+f",
"command": "workbench.action.tasks.runTask",
"args": "Gamble fail"
},
{
"key": "ctrl+g ctrl+p",
"command": "workbench.action.tasks.runTask",
"args": "Gamble pass"
},
]
Task Explorer extension can be installed to trigger using click
You want to :
have fun with a kind of programming game
learn or practice TDD
learn or practice TCR without the drawbacks
practice a new language
be driven by a strong methodology
be carried along by the strong methodology
practice breaking down your steps to achieve baby steps, using, for example :
You follow the Test F.I.R.S.T. Principles
You don’t really want to try this methodology
You will eventually cheat and lose the benefits while keeping some of the drawbacks
You don’t know what you want to achieve
Your tests :
ran very slowly
maybe a subset of the tests can be run to accelerate
are flaky
are not self-validating
You want to use double-loop TDD
unless you don’t run tests on bigger loops when you run smaller loops
TL;DR history will contain commits with only passing tests (with a nominal usage)
Long story : Yes and no
Yes, it does a commit at every step, including when tests are failing
And no, because it will amend the previous commit when :
gambling several times that the test fails
gambling that the pass after a gamble that the test fails
Commits with failing tests are temporary and should not end up in the history
Assuming every gamble were the good one, so everything is committed at each command
Doing the following commands :
git gamble --red --message "first iteration red"
git gamble --red --message "first iteration red edited" # improve the test
git gamble --green --message "first iteration green"
git gamble --red --message "second iteration red"
git gamble --green --message "second iteration green"
git gamble --refactor --message "second iteration refactor"
Will end with this git history :
gitGraph TB:
commit id:"initial commit"
commit id:"first iteration green"
commit id:"second iteration green"
commit id:"second iteration refactor"
The full history will look like this :
---
config:
theme: 'base'
---
gitGraph TB:
commit id:"initial commit"
branch GC_1
commit id:"(Dangling) first iteration red" type:REVERSE
switch main
branch GC_2
commit id:"(Dangling) first iteration red edited" type:REVERSE
switch main
commit id:"first iteration green"
branch GC_3
commit id:"(Dangling) second iteration red" type:REVERSE
switch main
commit id:"second iteration green"
commit id:"second iteration refactor"
Note : the GC_* branches are just a representation of dangling commits (Dangling) that will eventually be deleted by the garbage collector
The garbage collector is an automatic mechanism in git , nothing special have to be done
By default, the commit message is empty
Yes, not by default but given --allow-empty-message
This is an uncommon use case
The TCRDD methodology encourages doing baby steps
When doing so, the commits are so small that almost every time, the only possible message is describing what has been changed which a kind of repetition with the commit’s content
When gambling :
add a message with the option --message (or -m) followed by the message
git gamble --red --message "This is a great message"
open the default editor to write a message with the option --edit
git gamble --red --edit
It may be a good idea to add a message when enabling a feature flag
Add the end of iterations, the history can be rewritten using git rebase , commits can even be squashed
So it’s often a good idea to :
Take a break ⏸️
Slow down ⏳
Rollback the failing commit ⏪
Keep a branch if needed
git branch keep_it_for_maybe_later
Then actually rollback
git reset --hard @~
Refactor to “make the change easy” 🧠💡
for each desired change,
make the change easy
(warning: this may be hard) ,
then make the easy change
– Kent Beck 2012
Try to do smaller steps 👶🦶
If needed, try to reapply the failing commit ⏩
git cherry-pick keep_it_for_maybe_later --no-commit && git gamble --red
It may be in conflict depending on the changes made in previous steps ⚠️
git-gamble should work with all languages
It just need a test command that must :
exit with a 0 status when there are 0 failed tests
anything else is considered as a failure
It is independent of tools and editors
It could be integrated with tools and editors
To see real examples, read the usage examples
Any contributions (feedback, bug report , merge request …) are welcome
No question is too simple
Respect the code of conduct
Follow Keep a Changelog
The package is available on these repositories , and can be installed as usual if you use one of them
If the package is missing or not up to date in the repository that you prefer to use you can add it to the X package repository where the X package repository is e.g. Debian, Homebrew, Chocolatey …
Feel free to do it, we don’t plan to do it at the moment, it’s too long to learn and understand how each of them works
If you do it, please file an issue or open an MR to update the documentation
The following sections will help you to contribute with a merge request
The easiest way to get everything needed is to use Nix
This project is
Install Nix : to install dependencies
Install DirEnv : to install dependencies and set environment variables
Install Git : to get the repository
Get the source
git clone https://gitlab.com/pinage404/git-gamble
Switch to the directory
cd ./git-gamble
Note : if you only want to edit the documentation or slides , you can directly change the working directory to it, this will avoid downloading dependencies that you don’t need yet in the next step
cd ./docs
# or
# cd ./slides
Let DirEnv automagically set up the environment by executing the following command in the project directory
This will set up all required dependencies
direnv allow
To avoid rebuilding from scratch, Cachix can be used
cachix use git-gamble
If you get an error like this one when entering in the folder
direnv: loading ~/Project/git-gamble/.envrc
direnv: using nix
direnv: using cached derivation
direnv: eval /home/pinage404/Project/git-gamble/.direnv/cache-.336020.2128d0aa28e
direnv: loading ./script/setup_variables.sh
Compiling git-gamble v2.4.0-alpha.0 (/home/pinage404/Project/git-gamble)
direnv: ([/nix/store/19arfqh2anf3cxzy8zsiqp08xv6iq6nl-direnv-2.29.0/bin/direnv export fish]) is taking a while to execute. Use CTRL-C to give up.
error: linker `cc` not found
|
= note: No such file or directory (os error 2)
error: could not compile `git-gamble` due to previous error
Just run the following command to fix it
direnv reload
Help wanted to permanently fix this
Please reconsider using Nix because of the following advantages:
Ensure that the exact same versions will be installed, the versions that are known to work
Ensure the packages are installed in a way that works
All packages are installed, not only the rust toolchain, allowing you to work on any part
If you still want to avoid Nix, then follow these instructions:
Install Rustup
Start a new terminal to load the new configuration
Clone and navigate to git-gamble
git clone https://gitlab.com/pinage404/git-gamble.git
cd git-gamble
Install project-specific Rust toolchain and build the project
Running a build for the first time will install the toolchain from rust-toolchain.toml:
cargo build
Configure the environment
DirEnv is the recommended tool to set up the environment. If you don’t want to use it, then install and configure everything that should normally be installed by .envrc
Next, read the other files in the development section .
To list all available commands execute :
mask help
Most of the people use make to create users-friendly alias of complexes commands : a task runner
The make syntax is complicated because make is not only a task runner but a whole build system (and because make is old)
mask is an awesome task runner
mask is made to execute complexes commands using the Markdown syntax
So even if the people don’t understand that they could execute them using the mask command, they have a readable documentation of all the available commands because markdown could be rendered in a pretty readable format
The list below is a copy of maskfile.md
set -o errexit -o nounset -o pipefail -o errtrace
$MASK test shell
$MASK test rust
set -o errexit -o nounset -o pipefail -o errtrace
./tests/test_scripts.sh
./script/tests/test_generate_completion.sh
cargo test --features with_log
cargo feature-combinations --fail-fast test
./script/test_feature_combinations_with_coverage.sh
export RUST_LOG="trace"
export RUST_TRACE="full"
# export RUST_BACKTRACE="full"
export RUST_TEST_NOCAPTURE="display stdout and stderr"
cargo test \
--features with_log \
-- \
"$FILTERS"
bacon test --features with_log
cargo mutants
cargo feature-combinations --summary-only mutants
set -o errexit -o nounset -o pipefail -o errtrace
cargo clippy --all-targets --all-features
cargo check --all-targets --all-features
if command -v masklint >/dev/null; then
masklint run
fi
set -o errexit -o nounset -o pipefail -o errtrace
cargo feature-combinations --dedupe clippy --all-targets
cargo feature-combinations --dedupe check --all-targets
if command -v masklint >/dev/null; then
masklint run
fi
set -o errexit -o nounset -o pipefail -o errtrace
if command -v nix >/dev/null; then
# shellcheck disable=SC2046
nix fmt $(
find . \
-name "*.nix"
)
fi
cargo fix --all-features --allow-dirty --allow-staged
cargo fmt
set -o errexit -o nounset -o pipefail -o errtrace
git config core.hooksPath .config/git/hooks
git gamble hook enable time-keeper
git gamble hook enable assistant
git gamble hook enable sound
git config set hook.format.event pre-gamble
git config set hook.format.command 'sh -c "mask format"'
git config set hook.lint.event pre-gamble
git config set --comment 'lint are just here as a warning' hook.lint.command 'sh -c "mask lint || true"'
set -o errexit -o nounset -o pipefail -o errtrace
pushd ./docs/
direnv exec . \
mask docs serve
set -o errexit -o nounset -o pipefail -o errtrace
pushd ./slides/
direnv exec . \
mask slides serve "$SLIDE_FILE"
set -o errexit -o nounset -o pipefail -o errtrace
nix flake update
direnv exec . \
nix develop ".#update_rust_toolchain_to_the_latest_stable_version" --command \
update_rust_toolchain_to_the_latest_stable_version
direnv exec . \
cargo update
pushd ./slides
direnv exec . \
corepack use pnpm@latest
direnv exec . \
pnpm update --latest
This folder has been set up from the nix-sandboxes’s template
Folders structure and important files, detailing their purpose and primary technologies used
maskfile.md : Documents the main commands used in the development workflow
src/bin/ : Where the main() functions are, which are the entry points of the applications
Uses the clap library for handling command-line arguments
Delegates core functionality to git
tests/ : Tests the features of the programs
docs/ : Source of this documentation
Uses mdBook to generate documentation
Primarily from Markdown
Some Mermaid for diagrams
A few of HTML / CSS / JS
slides/ : Contains the source the slides
Uses Slidev to create slides
Primarily from Markdown
With some HTML / CSS / JS / Vue
flake.nix → nix/ : Manages development dependencies , packaging, templates…
Uses Snowfall/lib to scaffold files within the nix/ directory
script/ : Useful scripts to help the release process
.config/git/hooks/ : Examples of git hooks
There are some logs in the programs, pretty_env_logger is used to display them
There are 5 levels of logging (from the lightest to the most verbose) :
error
warn
info
debug
trace
The git-gamble logs are “hidden” behind the with_log feature
The option --features with_log (or --all-features) must be added to each cargo command for which you want to see logs (e.g.) :
cargo build --all-features
cargo run --all-features
cargo test --all-features
Then, to display logs, add this environment variable :
export RUST_LOG="git_gamble=debug"
To display really everything :
export RUST_LOG="trace"
There are other possibilities for logging in the env_logger documentation
You can also uncomment variables in the setup script
There is also a command that executes a test with all the outputs displayed
mask test rust debug <the test to filter>
Example
mask test rust debug commit_when_tests_fail
To verify that the code is actually tested by the tests, run the following command :
mask test rust mutants
To verify with all feature combinations, run the following command :
mask test rust mutants feature-combinations
Warning, this may take many times (~30 min)
At the beginning of the session, just run the following command :
watchexec -- git gamble --refactor
This is just TCR (without TDD )
git-gamble is basically an orchestrator around various git commands
There is very little logic in it
That is why testing the logic separately is not very useful :
it is not important to verify that the commands are called with specific options ;
what is important is the resulting behaviour, and that is what needs to be tested
For example :
verifying that git commit is called with the -m or --message option is not important ;
what is important is that the message passed as an argument is correctly recorded in the commit
Currently, the git command present in the $PATH is called directly ;
if in the future, a git library implemented in Rust was used instead, the tests would not need to be modified
Making an interface to test the code calling correctly git would be more or like creating a git library
It will still be necessary to test the implementation of this library
Just run cargo release (in a wide terminal, in order to have --help not truncated in the usage section )
cargo release
The following pages records architectural decisions
They use the Markdown Architectural Decision Records’s template
We (a colleague [referred to as “he” in the following text] and pinage404) used git-gamble at work
He was not used to using TDD or TCR
The fear of losing code led to an antipattern :
before gambling,
he took a lot of time to read the code carefully,
compile it and execute it in his head,
which slowed down the group
This strong methodology should lead you to let yourself be carried along by the tools
He recommended limiting the duration of iterations
git-gamble has been used by several groups and pinage404 has seen this antipattern several times
To solve the problem of iteration duration, another tool has been created since 2022-07-11 , but it is neither documented or easily distributed
The first version of git-time-keeper was written in Bash , and works most of the time , in order to have a more stable experience, it will be rewritten in Rust
git-gamble and git-time-keeper are tools that work independently and can be used together for an optimal experience
How to create, maintain and distribute several tools ?
from the maintainer’s point of view
easy to set up
easy to maintain
easy to distribute
avoid duplication of configuration and utilities
from the user’s point of view
easy to install
easy to use
easy to understand that each tool can be used separately
easy to use tools together for an optimal experience
Repos : several independent repositories
Workspaces : 1 repository with several Cargo workspaces
Binaries : 1 repository with 1 crate containing several binaries
Chosen option: “Binaries”, because this solution seems to have the fewest downsides, see the table below
Repos Workspaces Binaries
Maintainer
easy to set up Good , easiest, just git cloneBad , need a little of workNeutral , Good if every tool support it
easy to maintain Bad , need to maintain several reposGood , that’s what workspaces are forNeutral , easy but risk of confusion between what belongs to which tool
easy to distribute Bad , need to re-setup external platformsNeutral if every tool support itNeutral , Good if every tool support it
avoid duplication Bad Neutral , can have a shared CrateGood
User
easy to install Bad , need several installationsNeutral Neutral , Good if every tool support it
easy to use Neutral Neutral Neutral
understand tools are independent Good Neutral Neutral
easy to use tools together Bad Neutral Neutral
Total Good 2 Neutral 1 Bad 5 = -3 Good 1 Neutral 6 Bad 1 = 0 Good 1 Neutral 7 Bad 0 = +1
There is no single source of truth between local development and the pipeline
Tools are defined in different files
The versions of the tools used are not the same, depending on the package manager used to install the tools
Debian-based container images are big
Past attempts have been failures to make working build with Alpine based container, because Alpine use Musl instead of GLibC
The image created from ci/rust_with_git.Dockerfile
FROM rust:1.80-slim-bookworm
RUN apt-get --quiet=2 update \
&& apt-get --quiet=2 install --no-install-recommends \
git \
&& apt-get --quiet=2 clean \
&& rm --force --recursive /var/lib/apt/lists/*
Using the following commands
docker build -f ./ci/rust_with_git.Dockerfile ./ci/
dive sha256:443b8185bfb389687697e4193b569feb40a3e0b5a2b023562f8da279516f5d83
Total Image size: 854MB
Potential wasted space: 4.7 MB
Image efficiency score: 99 %
Update is done manually in each Dockerfile, in the FROM ; which is not convenient
Open source
Price : must be free or very low
High reproducibility
Ability to use cache (Nix’s cache or GitLab’s cache)
Lighter
Faster
Use of standard tools
Using external services
Using GitLab only
Replace image building with Kaniko in the pipeline
with image building with Nix
Try using GitLab’s Cache or Cachix using Cynerd’s gitlab-ci-nix example (the tool or the idea made by the tool) to save Nix Store.
Good , single source of truth for the versions used (which ends up to flake.lock)
Good , update process is already handled automatically
Just execute
nix flake update
Good , use open source tools
Maybe not the Cachix server which will maybe used
Good , free
Good , high reproducibility
Good , cache may be used
Bad , the images are twice bigger
It could probably be optimized
Bad , expect to be slower , because of the image size
On self-hosted runner, it will use Docker’s cache
Good , don’t use a niche tool
NixCI
Source not found
Only one dev behind it ?
What about the maintainability ? ⚠ ️
The page talks about GitLab integration
There is no call to action for GitLab
Don’t know how to use it with GitLab 🤷
Is it SaaS or Self Hosted ?
There are machines that will compute stuff
Who pays ? Pricing is unclear 💸
The page talks about self-hostable
Don’t found the documentation 🤷
Need scaring authorization on GitHub : Act on your behalf 🤨
The page looks more like a roadmap than the documentation of actual functionalities
Doesn’t look trustworthy
Need to move to GitHub
GitHub is not Open Source ❌
Garnix
Pricing have a free tier (1 500 minutes/month) that may be enough 💶
Cachix
Already used in the pipeline 👍
Jetify Cache
Pricing seems to start from $5/month + $0.60 Go/month 💰
Don’t found the sources ❌
Vonfry’s gitlab-ci-nix example
By GitLab CI itself , download previous cache, if any ⬇ ️
Import derivations to Nix Store from cache , if any ⬅ ️
Do stuff ⚙ ️
Export all derivations from Nix Store to cache ➡ ️
By GitLab CI itself , upload cache ⬆ ️
Cynerd’s gitlab-ci-nix example
By GitLab CI itself , download previous cache, if any ⬇ ️
Set substituters : local cache, Cachix, S3, SSH , if any ⬅ ️
Save current derivations
Do stuff ⚙ ️
List new derivations by comparing current derivations with the saved ones
Export new derivations from Nix Store to cache ➡ ️
Upload new derivations to Cachix, S3, SSH , if any ⬆ ️
By GitLab CI itself , upload cache ⬆ ️
TECHNOFAB’s nix-gitlab-ci template
Declare pipeline using Nix instead of YAML
Seems easy to test locally
declare the pipeline using Nix
generate the .gitlab-ci.yaml
trigger a pipeline from the generated .gitlab-ci.yaml
The generated pipeline works likely Cynerd’s version
Support GitLab’s Cache, Cachix , and Attic
As the time pass, the cache will grow, it will slow the pipeline 📈
Every cache paths will be downloaded and reuploaded at each pipeline, not only the ones that are actually needed for the current job
How to do clean unnecessary paths ? 🚮
Should an extra step with nix-gc be added ?
Without erasing everything periodically ?
🆚 Vonfry’s version Cynerd’s version TECHNOFAB’s version
Complexity Simpler ✅ More complex 👎 Even more complex 😵
Cache Naive ❌ Optimized ✅ Optimized ✅
Reusability Just an example ❌ Made for ✅ Made for ✅
Reproducibility Not versioned 👎 Not versioned 👎 Have releases ✅
Use container from nixos/nix and run the following command inside
direnv allow
Pro : simple ✅
Const : don’t use cache, so download everything from scratch at each job ❌
Won’t use GitLab’s cache ❌
Download a base image
Install Nix inside GitLab’s job
Install packages using Nix
Seems to be heavy
{
lib,
pkgs,
}:
let
rustupToolchainFile = lib.snowfall.fs.get-file "rust-toolchain.toml";
rust-toolchain = pkgs.rust-bin.fromRustupToolchainFile rustupToolchainFile;
in
pkgs.dockerTools.buildImage {
name = "build-image";
copyToRoot = [
rust-toolchain
pkgs.dockerTools.binSh
];
}
nix build '.#build-image'
dive --source docker-archive <(gunzip -c ./result)
Total Image size: 1.9 GB
Potential wasted space: 0 B
Image efficiency score: 100 %
{
lib,
pkgs,
}:
let
rustupToolchainFile = lib.snowfall.fs.get-file "rust-toolchain.toml";
rust-toolchain = pkgs.rust-bin.fromRustupToolchainFile rustupToolchainFile;
in
pkgs.dockerTools.buildLayeredImage {
name = "build-layered-image";
contents = [
rust-toolchain
pkgs.dockerTools.binSh
];
}
nix build '.#build-layered-image'
dive --source docker-archive <(gunzip -c ./result)
Total Image size: 1.7 GB
Potential wasted space: 0 B
Image efficiency score: 100 %
Same when trying to limit max layers
{
lib,
pkgs,
}:
let
rustupToolchainFile = lib.snowfall.fs.get-file "rust-toolchain.toml";
rust-toolchain = pkgs.rust-bin.fromRustupToolchainFile rustupToolchainFile;
in
pkgs.dockerTools.buildLayeredImage {
name = "build-layered-image-limit-layers";
contents = [
rust-toolchain
pkgs.dockerTools.binSh
];
maxLayers = 2;
}
nix build '.#build-layered-image-limit-layers'
dive --source docker-archive <(gunzip -c ./result)
Total Image size: 1.7 GB
Potential wasted space: 0 B
Image efficiency score: 100 %
Same when trying to remove components to remove the rust’s source
{
lib,
pkgs,
}:
let
rustupToolchainFile = lib.snowfall.fs.get-file "rust-toolchain.toml";
rustupToolchainFileContent = lib.trivial.importTOML rustupToolchainFile;
rustupToolchain = rustupToolchainFileContent.toolchain;
rustupToolchainCleaned = lib.snowfall.attrs.merge-deep [
rustupToolchain
{ components = [ ]; }
];
rust-toolchain = pkgs.rust-bin.fromRustupToolchain rustupToolchainCleaned;
in
pkgs.dockerTools.buildLayeredImage {
name = "build-layered-image-no-rust-src";
contents = [
rust-toolchain
pkgs.dockerTools.binSh
];
}
nix build '.#build-layered-image-no-rust-src'
dive --source docker-archive <(gunzip -c ./result)
Total Image size: 1.7 GB
Potential wasted space: 0 B
Image efficiency score: 100 %
{
lib,
pkgs,
}:
let
rustupToolchainFile = lib.snowfall.fs.get-file "rust-toolchain.toml";
rust-toolchain = pkgs.rust-bin.fromRustupToolchainFile rustupToolchainFile;
in
pkgs.dockerTools.streamLayeredImage {
name = "stream-layered-image";
contents = [
rust-toolchain
pkgs.dockerTools.binSh
];
}
nix build '.#stream-layered-image'
./result > stream-layered-image.tar
dive docker-archive://./stream-layered-image.tar
Total Image size: 1.7 GB
Potential wasted space: 0 B
Image efficiency score: 100 %
nix2container generate the JSON that describe the container where the layers are derivation linked to the Nix store
The article that explain what does it solve
{
lib,
pkgs,
}:
let
rustupToolchainFile = lib.snowfall.fs.get-file "rust-toolchain.toml";
rust-toolchain = pkgs.rust-bin.fromRustupToolchainFile rustupToolchainFile;
in
pkgs.nix2containerPkgs.nix2container.buildImage {
name = "nix2container";
copyToRoot = pkgs.buildEnv {
name = "root";
paths = [
rust-toolchain
pkgs.dockerTools.binSh
];
pathsToLink = [ "/bin" ];
};
}
nix run '.#nix2container.copyToDockerDaemon'
dive nix2container:cvlrpzfkvq2y0q99aa8csni1r6znl3bg
Total Image size: 1.7 GB
Potential wasted space: 0 B
Image efficiency score: 100 %
buildImagebuildLayeredImagestreamLayeredImagenix2container
Nix Store GZipped Image GZipped Image Script + JSON JSON
Layers 1 Several Several 1
Image size 1.9 GB 1.7 GB 1.7 GB 1.7GB
Rust’s source code, Linux’s headers, locales, documentation and manual pages are included
It could probably be removed with more configuration
Git 2.54 introduced a new way to declare git hooks (and also other cool unrelated stuffs)
git-gamble’s current implementation (2.12.1), manually executes git hooks file
Defining git-gamble’s hook with the new format will ignore these hooks (demo )
easy to implement
easy to maintain
keep some kind of backward compatibility
Chosen options : use internal git-hook run command and add Cargo feature to disable git-gamble’s hooks
It would be easy to implement, easy to maintain
With some documentation, it would allow people using and old version of git to remove git-gamble’s hooks
Testing the combination of all Cargo features, will take some times but could be automatised
This is the current behavior until git-gamble 2.12.1
Good , nothing to do, the easiest solution
Bad , users may be confused : some hook (git’s hooks) work, but others (git-gamble’s hook) don’t
Bad , this introduces a difference in the behavior of git and git-gamble
Current implementation reimplement how hook file works, so it Could be logic to reimplement how new hooks format works
Bad , this is the solution is hard to implement
Bad , it would be not future-proof, the maintenance may be hard
Since git 2.36, there is the command git-hook run
git 2.36 have been released the 2022-04-18
Replacing the current implementation by this command will make git-gamble requiring git 2.36 or above
As the time of writing (2026-05-09), according to Repology , this would break some LTS distributions
Like :
The Long Term Support distributions target servers, not really for daily use like a developer computer
Bad , a user with an old git version won’t be able to use git-gamble at all, this would break backward compatibility
A detection of the git version could be done, to know which strategy to use :
git 2.54 or newer ⇒ use git hook run
else ⇒ manually execute file
So :
Bad , it won’t be easy to implement
Bad , it would make the code more complicated for something that would eventually disappear, so bad for the maintenance
Add a Cargo feature to remove all the hook related stuff at compilation
The feature would be enabled by default
The feature could be disabled and git-gamble compiled to works on old distributions
Good , it is easy to implement
Neutral , it would require some documentation to explain how to do that and when to do that
Bad , testing the combinations of all Cargo features takes more time
The following pages document work in progress that has not yet been published
All or part of it is subject to change without notice
git-time-keeper
is a tool that helps to take baby steps 👶🦶
git-time-keeper
can be used as a companion tool to
git-gamble
or can be used separately
Read the hooks examples documentation
Without git-gamble
# git config --local core.hooksPath ./hooks # if you want to version hooks
HOOKS_PATH=$(git rev-parse --git-path hooks)
mkdir -p "$HOOKS_PATH"
echo "git-time-keeper 'stop'" >>"$HOOKS_PATH/pre-commit"
echo "git-time-keeper 'start'" >>"$HOOKS_PATH/post-commit"
chmod +x "$HOOKS_PATH"/{pre,post}-commit
export TIME_KEEPER_MAXIMUM_ITERATION_DURATION=$((3 * 60)) # 3 minutes
In order to avoid conflict while saving
between the content stored on the disk and the content in the editor,
it is recommended to enable autosave
(at least for the current project)
For VSCode, you can set files.autoSave to afterDelay
You can run this command to do it for you
SETTINGS="./.vscode/settings.json"
if [ ! -f "$SETTINGS" ]; then
echo '{
"files.autoSave": "afterDelay",
}' >"$SETTINGS"
elif grep 'files.autoSave' "$SETTINGS" >/dev/null; then
sed -Ei 's@"files.autoSave": "[a-zA-Z]+"@"files.autoSave": "afterDelay"@' "$SETTINGS"
else
sed -i 's@^{@{\n "files.autoSave": "afterDelay",@' "$SETTINGS"
fi
When being on time
sequenceDiagram
actor Dev
participant git
participant hooks
participant git-time-keeper
Dev->>git: git commit
git->>hooks: git hook run pre-commit
hooks-xgit-time-keeper: git time-keeper stop
git->>hooks: git hook run post-commit
hooks-)+git-time-keeper: git time-keeper start
Dev->>git: git commit
git->>hooks: git hook run pre-commit
hooks-)git-time-keeper: git time-keeper stop
git-time-keeper-->-hooks: timer stopped
git->>hooks: git hook run post-commit
hooks-xgit-time-keeper: git time-keeper start
When the countdown is missed
sequenceDiagram
actor Dev
participant git
participant hooks
participant git-time-keeper
Dev->>git: git commit
git->>hooks: git hook run pre-commit
hooks-xgit-time-keeper: git time-keeper stop
git->>hooks: git hook run post-commit
hooks-)+git-time-keeper: git time-keeper start
git-time-keeper-)git-time-keeper: time limit passed
git-time-keeper-)-git: git restore .
To see all available flags and options
git time-keeper --help
Dash - between git and time-keeper may be only needed for --help
git-time-keeper --help
git time-keeper --help
Usage: git-time-keeper [OPTIONS]
Options:
-h, --help Print help
-V, --version Print version
Any contributions (feedback, bug report, merge request ...) are welcome
https://gitlab.com/pinage404/git-gamble
stateDiagram
state "Timer is running" as running
state "git restore ." as clean
[*] --> running : start
running --> [*] : stop
running --> clean : time limit passed
clean --> [*]
running --> running : start
[*] --> [*] : stop
Unix compatible only (Linux / macOS) : need sh and kill
This project adheres to Semantic Versioning
The release notes will be posted at each version
Follow on your preferred social media :
@git-gamble.is-cool.dev@web.brid.gy
@git-gamble.is-cool.dev
The release notes will be posted at each version
Follow with your preferred format :
The release notes will be posted at each version
Follow on your preferred social media :
@git-gamble.is-cool.dev@web.brid.gy
@git-gamble.is-cool.dev
Note
Nice domain name on Fediverse is blocked by this GitLab Pages issue
The Fediverse URL may change when this issue will be resolved
Upvote the issue 👍 if you want to express that you would like this to be prioritized
The release notes will be posted at each version
Follow with your preferred format :
use upstream mdBook version
add link to release page in the changelog pages
this project doesn’t use strictly Keep a Changelog since a while
prefer to group changes related to the scope together (features, docs, technical…) than just group by status (added, changed, removed…)
Full changelog
Release page with release artifacts
Full changelog
release archive with binaries (git-gamble and git-time-keeper)
Release page with release artifacts
Full changelog
Release page with release artifacts
Full changelog
release with tag vX.Y.Z instead of version/X.Y.Z
fix artifacts upload on release
Release page with release artifacts
Full changelog
add Cargo features to disable some tests related to specific git’s version
with_git_2_36_0
with_git_2_54_0
help packaging with Nix : less strict text generation in hooks, not using shebang
fix AppVeyor’s pipeline (which was broken since 2 years 🫣)
update dependencies
Release page with release artifacts
Full changelog
Release page with release artifacts
Full changelog
rename Cargo feature from with_shell_completions to with_subcommand_generate_shell_completions
rename hook
from
post-gamble.real_time_collaboration.sample.sh
to
post-gamble.real-time-collaboration.sample.sh
rename git-time-keeper’s git’s hooks
from
pre-commit.time-keeper.sample.sh
post-commit.time-keeper.sample.sh
to
pre-commit.time-keeper-git-only.sample.sh
post-commit.time-keeper-git-only.sample.sh
fix pipeline
bump dependencies
Release page with release artifacts
Full changelog
Release page with release artifacts
Full changelog
Starting with git-gamble 2.13.0, it requires git version 2.36 or higher
git 2.36 was released the 2022-04-18, and is now available in most package managers
To use git-gamble with git below 2.36, git-gamble’s hooks must be disabled by installing git-gamble with the option to disable the feature
support new git hook format introduced in git 2.54 (and also introduced other cool unrelated stuffs)
display more help messages ; Closes Issue #10
when the test command can’t be executed
like when the test command does not exist or is not found in the $PATH
when git can’t be executed
like when it is not installed or is not found in the $PATH
allow to remove optional features at compile time, they are enabled by default ; this was a first step for Issue #10
with_custom_hooks : to use custom hooks
with_shell_completions : to enable shell completions
display all errors in stdout instead of stderr
previously some errors were displayed on stdout, others on stderr
the boundary between a warning and an error is blurry
build slides in the pipeline with Gitlab.org worker
.unwrap() and .expect()
in source, replace .unwrap() with .expect() to have at least an error message
in tests, replace .expect() with .unwrap() a specific message is not needed in tests, because we have the source code just aside
upgrade glab from 1.90.0 to 1.97.0
bump Rust from 1.94.0 to 1.95.0
bump dependencies
Release page with release artifacts
Full changelog
upgrade glab from 1.61.0 to 1.90.0 to try to fix the release step in the pipeline
Release page with release artifacts
Full changelog
display more help messages
when a commit fails ; Thanks @wonderbird (Stefan Boos) for the report Issue #9
the most likely scenario is when a pre-commit hook fail
possible other case (not likely a normal scenario) when an internal command (git) receive a signal (SIGKILL) while running
when the test command can’t be parsed
when a post-gamble hook fails
since version/2.11.0 , when a pre-gamble hook fails, it explains what happened and how to debug
before :
always pretends that the pre-gamble hook exited with code 1
after :
displays the pre-gamble hook exited code
upgrade mdBook to 0.5
bump Rust from 1.88.0 to 1.94.0
bump dependencies
try to have more idiomatic Rust code ; Thanks @ToF- (ToF) & @etienneCharignon (Étienne Charignon) for the idea
try to avoid panicking in a deep function calls (with .unwrap() or .expect()) ; Thanks @ToF- (ToF) for the idea
some remaining, it is hard to write tests on them
split logic between informing / warning / “erroring” a message and displaying it ; Thanks @etienneCharignon (Étienne Charignon) for the idea
Release page with release artifacts
Full changelog
help users to open issues
bump Rust from 1.85.0 to 1.88.0
bump dependencies
Release page with release artifacts
Full changelog
fix git-time-keeper when used according to the documentation, an error message was displayed when used with git-gamble
note: git-time-keeper is still in beta
starting from 2.9.0
update Chocolatey package’s version on release
fix Chocolatey link in the release’s artifact
remove AppImage distribution Issue #8
remove support of legacy Nix, prefer using Nix Flake
use Snowfall Lib to simplify Nix stuff with convention over configuration
bump dependencies
bump Rust from 1.80 to 1.85.0
bump Rust’s edition from 2021 to 2024
in the pipeline, container images are generated from Dockerfile to Nix
Release page with release artifacts
Full changelog
previously, untracked files were not deleted in case of a bad gamble ; now, untracked files are deleted in case of a bad gamble ; Thanks @kevin.hantzen (k.hantzen) for the idea Issue #3
previously, gambling --green with a clean repository failed ; now, it warns that there is nothing to commit ; Thanks @contet (Thomas Conte) for the idea
bump dependencies
bump Rust from 1.78 to 1.80
Release page with release artifacts
Full changelog
previously, gambling --green with --fixup (e.g. git gamble --green --fixup ":/some commit") just after a git gamble --red failed ; this has been fixed ; Contribution by @korrat (Markus Haug) in MR !5
improve manual page
bump Rust from 1.75 to 1.78
update dependencies
fix flaky test ; Contribution by @korrat (Markus Haug) in MR !6
replace NPM with PNPM
Release page with release artifacts
Full changelog
add human-panic , a tool that encourages users who experience a crash to report it
add compose.yml file to help to debug the CI
bump container image from Debian Buster to Bookworm
bump Rust from 1.73 to 1.75
bump dependencies
Release page with release artifacts
Full changelog
when generating shell completion, if the user doesn’t give the target shell, try to determine the current shell from the environment or default to Bash
Release page with release artifacts
Full changelog
setup Gitpod to help contributions
Release page with release artifacts
Full changelog
bump some dependencies
use Nix Flake to generate environment with nix-shell or nix develop
use devshell to have commands shortcuts
bump Rust from 1.55 to 1.60
ignore audit dependency because there is no safe upgrade available
release only on main
Release page with release artifacts
Full changelog
auto updated git gamble generate-shell-completions --help in README
publish Linux and Windows binaries in releases
fix markdownlint issues
hardcode TOC generated by Markdown All In One instead of the one generated by GitLab
faster CI by removing useless job
generate test coverage
Release page with release artifacts
Full changelog
Fix deployment on crate.io
Release page with release artifacts
Full changelog
Wrap git-gamble --help based on the terminal size
auto updated git-gamble --help in README
Improve release binary size thanks to this post
from 5 934 760 octets (~6Mo) to 772 416 octets (<1Mo)
Release page with release artifacts
Full changelog
improve git-gamble --help
add color
reorder --fail, --pass and --refactor flags
add description of the program
add link to the repository
generate shell completions using the subcommand git gamble generate-shell-completions
update release-cli
explicitly set rustc as a dependency
Release page with release artifacts
Full changelog
⚠️ BREAKING CHANGE ⚠️ remove BinTray package publishing
smaller container image in CI
upload only required files to crates.io, thanks to cargo-diet
bump Rust from 1.50 to 1.55
bump some dependencies
remove some linters warnings
allow git-gamble to run inside nix-shell
explicitly set cargo as a dependency
rename default branch from master to main
Release page with release artifacts
Full changelog
Packages repositories will be moved on GitLab because JFrog will shut down BinTray
Please follow installation instructions for your specific system
Affected by this changement
⚠️ Automatic update won’t work in the future ⚠️
There is not automatic update system at the moment, you already have to manually update at each new version
Not affected by this changement
Mac OS X / Homebrew
Nix / NixOS
Cargo
This will be a kind of ⚠️ BREAKING CHANGE ⚠️ : 2.0.0 won’t be on BinTray
bump image’s version for the CI’s container
bump Kaniko’s version to build the CI’s container
Release page with release artifacts
Full changelog
remove warning at compile time (while using cargo test) ; Contribution by @bachrc in MR !1
improve the speed of the CI
improve the way to set up the development environment
bump Rust to 1.50
bump dependencies
Full changelog
custom logo
shells completions
automatically installed with Debian and Homebrew packages
only for Bash, Fish, ZSH
Full changelog
Initial project
With the minimum functionalities required for real life use
Installable on Linux, Mac OS X and Windows
Full changelog
git workspace support
git update-ref should contain a unique identifier to the workspace
branch name ?
folder path ?
gamble hooks
branch based development
git commit --fixup
git rebase --autosquash
optional hook to revert if not gambled in a delay
git-time-keeper
document
package
distribute
like git, flags & options & arguments should be retrieved from CLI or environment variable or config’s file
re-use git config to store in file ?
repository level config using direnv and environment variable ?
stash instead of revert ?
shell completion
in the package ?
for git gamble not only git-gamble
https://gitlab.com/gitlab-org/security-products/analyzers
https://gitlab.com/gitlab-org/security-products/ci-templates
https://medium.com/@tdeniffel/tcr-variants-test-commit-revert-bf6bd84b17d3
https://svgfilters.com/
https://github.com/llogiq/mutagen
OS distribution
permanent URL to download latest version
symlinks to URL containing the version name ?
using GitLab Pages ?
versioned Homebrew Formula
Use Cargo-Release to bump version
how to update sha256 in the versioned file ?