Easily manage git hooks in your composer config

Overview

composer-git-hooks

Software License Travis Packagist Download

Manage git hooks easily in your composer configuration. This command line tool makes it easy to implement a consistent project-wide usage of git hooks. Specifying hooks in the composer file makes them available for every member of the project team. This provides a consistent environment and behavior for everyone which is great. It is also possible to use to manage git hooks globally for every repository on your computer. That way you have a reliable set of hooks crafted by yourself for every project you choose to work on.

Install

Add a hooks section to the extra section of your composer.json and add the hooks there.

{
    "extra": {
        "hooks": {
            "pre-commit": [
                "echo committing as $(git config user.name)",
                "php-cs-fixer fix ." // fix style
            ],
            // verify commit message. ex: ABC-123: Fix everything
            "commit-msg": "grep -q '[A-Z]+-[0-9]+.*' $1",
            "pre-push": [
                "php-cs-fixer fix --dry-run ." // check style
                "phpunit"
            ],
            "post-merge": "composer install"
            "...": "..."
        }
    }
}

Then install with

composer require --dev brainmaestro/composer-git-hooks

This installs the cghooks binary to your vendor/bin folder. If this folder is not in your path, you will need to preface every command with vendor/bin/.

Note: hooks declared in the scripts or hooks root sections of composer.json are no longer supported in v3.

Global support

You can also install it globally. This feels much more natural when cghooks is used with the newly added support for managing global git hooks.

composer global require --dev brainmaestro/composer-git-hooks

All commands have global support (besides testing the hooks. Still requires being in the directory with the composer.json file).

Optional Configuration

Stop on failure

When a hook is a sequence of commands, it can be useful to stop the execution when a command fails.

Specify the impacted hooks in the stop-on-failure config section.

{
    "extra": {
        "hooks": {
            "config": {
                "stop-on-failure": ["pre-push"]
            },
            "pre-push": [
                "php-cs-fixer fix --dry-run --stop-on-violation .",
                "phpunit"
            ],
        }
    }
}

Always be sure to run the update command after changing the stop-on-failure config section.

Custom hooks

Custom hooks can be added to the custom-hooks array of the `config section.

{
    "extra": {
        "hooks": {
            "config": {
                "custom-hooks": ["pre-flow-feature-start"]
            },
            "pre-flow-feature-start": [
                "echo 'Starting a new feature...'"
            ]
        }
    }
}

Always be sure to run the update command after changing the custom-hooks config section. Note: config is not valid custom hook value.

Shortcut

Add a cghooks script to the scripts section of your composer.json file. That way, commands can be run with composer cghooks ${command}. This is ideal if you would rather not edit your system path.

{
    "scripts": {
        "cghooks": "vendor/bin/cghooks",
        "...": "..."
    }
}

Composer Events

Add the following events to your composer.json file. The cghooks commands will be run every time the events occur. Go to Composer Command Events for more details about composer's event system.

{
    "scripts": {
        "post-install-cmd": "cghooks add --ignore-lock",
        "post-update-cmd": "cghooks update",
        "...": "..."
    }
}

Usage

All the following commands have to be run either in the same folder as your composer.json file or by specifying the --git-dir option to point to a folder with a composer.json file.

Adding Hooks

After installation is complete, run cghooks add to add all the valid git hooks that have been specified in the composer config.

Option Description Command
no-lock Do not create a lock file cghooks add --no-lock
ignore-lock Add the lock file to .gitignore cghooks add --ignore-lock
force-win Force windows bash compatibility cghooks add --force-win

The lock file contains a list of all added hooks.

If the --global flag is used, the hooks will be added globally, and the global git config will also be modified. If no directory is provided, there is a fallback to the current core.hooksPath in the global config. If that value is not set, it defaults to $COMPOSER_HOME (this specific fallback only happens for the add command). It will fail with an error if there is still no path after the fallbacks.

Updating Hooks

The update command which is run with cghooks update basically ignores the lock file and tries to add hooks from the composer file. This is similar to what the --force option for the add command did. This command is useful if the hooks in the composer.json file have changed since the first time the hooks were added.

This works similarly when used with --global except that there is no fallback to $COMPOSER_HOME if no directory is provided.

Removing Hooks

Hooks can be easily removed with cghooks remove. This will remove all the hooks that were specified in the composer config.

Hooks can also be removed by passing them as arguments. The command cghooks remove pre-commit post-commit which will remove the pre-commit and post-commit hooks.

Option Description Command
force Delete hooks without checking the lock file cghooks remove --force

CAREFUL: If the lock file was tampered with or the force option was used, hooks that already existed before using this package, but were specified in the composer scripts config will be removed as well. That is, if you had a previous pre-commit hook, but your current composer config also has a pre-commit hook, this option will cause the command to remove your initial hook.

This also does not have a fallback to $COMPOSER_HOME if no directory is provided when used with --global.

Listing hooks

Hooks can be listed with the cghooks list-hooks command. This basically checks composer config and list the hooks that actually have files.

Common Options

The following options are common to all commands.

Option Description Command
git-dir Path to git directory cghooks ${command} --git-dir='/path/to/.git'
lock-dir Path to lock file directory cghooks ${command} --lock-dir='/path/to/lock'
global Runs the specified command globally cghooks ${command} --global

Each command also has a flag -v to control verbosity for more detailed logs. Currently, only one level is supported.

Testing Hooks

Hooks can be tested with cghooks ${hook} before adding them. Example cghooks pre-commit runs the pre-commit hook.

Contributing

Please see CONTRIBUTING for details.

Credits

Related

License

The MIT License (MIT). Please see License File for more information.

Comments
  • About the post-install-cmd example and installing with --no-dev

    About the post-install-cmd example and installing with --no-dev

    Hi! I found this package extra useful for my workflow at my job. I just wanted to share my experience implementing it and a couple of thoughts.

    I felt the "post-install-cmd": "cghooks add --ignore-lock", suggestion very misleading, if I understood correctly, it would add the cghooks.lock file to my gitignore (in my case breaking my gitignore, as the last line was not empty), and my coworker would get the gitignore modified too (as the package would not find a cghooks.lock file.

    On the other hand, I had issues when doing a composer install --no-dev deploy.

    My first attemp was checking the COMPOSER_DEV_MODE env variable, but it did not work in my Docker environment. I solved it with a command -v call. Also, I had to specify the git-dir because the package was not finding it on my Docker container (and I don't have any clue about why).

    My last problem appeared when doing composer install after a composer install --no-dev. I had to solve this by uninstalling the hooks before every installation.

    This is an excerpt of my final composer.json file. I think that the readme could be improved, and the workflow rethinked to be easier!

    {
    	"require-dev": {
    		"overtrue/phplint": "^1.1",
    		"brainmaestro/composer-git-hooks": "^2.8"
    	},
    	"scripts": {
    		"pre-install-cmd": "command -v vendor/bin/cghooks >/dev/null 2>&1 || exit 0; vendor/bin/cghooks remove --git-dir=.git",
    		"post-install-cmd": "command -v vendor/bin/cghooks >/dev/null 2>&1 || exit 0; vendor/bin/cghooks add --git-dir=.git",
    		"post-update-cmd": "command -v vendor/bin/cghooks >/dev/null 2>&1 || exit 0; vendor/bin/cghooks update --git-dir=.git",
    		"phplint": "./vendor/bin/phplint",
    		"test": [
    			"@composer run phplint"
    		]
    	},
    	"scripts-descriptions": {
    		"test": "Run all tests"
    	},
    	"extra": {
    		"hooks": {
    			"pre-commit": [
    				"composer run test"
    			],
    			"post-merge": "composer install"
    		}
    	}
    }
    
    opened by devnix 43
  • Allow custom hooks from config section

    Allow custom hooks from config section

    Hi, This prevent adding test command for non valid hooks. For now every scripts of the file and the config section are listed in the possible commands. Thanks

    opened by shaffe-fr 17
  • Update to Symfony 6, PHP-CS-Fixer 3 and PHPUnit 9.5

    Update to Symfony 6, PHP-CS-Fixer 3 and PHPUnit 9.5

    Closes #123

    Changed:

    • Updated to Symfony\Console ^6.0
    • Updated to PHP-CS-Fixer ^3.0
    • Updated to PHPUnit ^9.5
      • Rename assertContains to assertStringContainsString
      • Rename assertNotContains to assertStringNotContainsString
      • Rename `assertFileNotExists' to 'assertFileDoesNotExist'
    • Updated to PHP ^8.0
    • Updated GitHub Actions workflows
    • Make constants public (Hook.php)
    • Cast shell_exec output to string (src/helpers.php) because trim required a string and not string|ƒalse|null

    Added

    • Added file_exists check before create a directory

    EDIT: For these wanting to try out these changes you can do the following to your composer.json:

    {
        "repositories": [
            {
                "type": "git",
                "url": "https://github.com/Jubeki/composer-git-hooks"
            }
        ],
        "require-dev": {
            "brainmaestro/composer-git-hooks": "dev-prepare-for-symfony-6"
        },
        "minimum-stability": "dev",
        "prefer-stable": true
    }
    
    opened by Jubeki 13
  • git commit not committing after completing pre-commit scripts

    git commit not committing after completing pre-commit scripts

    This is probably a dumb question or something simple I am overlooking but for some reason no matter what I do I cannot seem to get my git commit -m"message here" to actually commit upon completion of the pre-commit hook. I have seen elsewhere online where if the hook returns 0 then the commit should complete as expected. I have even added multiple variations of exit 0 as the last script within the pre-commit array but with no luck.

    • I have tried composer dump-autoload, composer cghooks update, etc.
    • I have also installed cghooks both locally within the project and globally within composer.

    The pre-commit hooks is running as expected but fails to actually add the new commit upon completion.

    Not sure if this helps but I am working on a Laravel 5.8 project using and using the virtual box vm 'laravel/homestead' version '7.1.0'.

    I have spent more time than I'd like to admit trying to get this to work so any help would be greatly appreciated. I hope this is the right channel to post this. Thanks!

    When running git commit and then git status:

    vagrant@homestead:~/code/notiifii$ git commit -m"test" committing as [email protected] Loaded config default from ".php_cs".

    Fixed all files in 13.107 seconds, 12.000 MB memory used

    vagrant@homestead:~/code/notiifii$ git status On branch master Your branch is up to date with 'origin/master'.

    Changes to be committed: (use "git reset HEAD ..." to unstage)

    modified:   .gitignore
    new file:   .php_cs
    modified:   app/Console/Kernel.php
    modified:   composer.json
    modified:   composer.lock
    modified:   routes/web.php
    

    Here is the hooks section of my composer.json file. These are found under the extra section.

    "hooks": { "pre-commit": [ "echo committing as $(git config user.email)", "php-cs-fixer fix --config=.php_cs", "git add ." ], "pre-push": [ "php-cs-fixer fix --dry-run --config=.php_cs", "phpunit" ], "post-merge": "composer install" },

    opened by tylerrehm-id 12
  • Update code for the git file issue

    Update code for the git file issue

    I have added, ability to find git directory, this code will try to find out .git directory from the root of the project as well as the parent directory of the project.

    Most of have git initialize in their parent directory and composer in root directory so package will create git inside the folder where composer is placed.

    This PR issue is mentioned here https://github.com/BrainMaestro/composer-git-hooks/issues/54

    opened by aman00323 12
  • Support PHP 7.3

    Support PHP 7.3

    Would be awesome if you could support PHP 7.3 Right now the requirements are set to < 7.3 thus its not installable without the --ignore-platform-reqs arg.

    brainmaestro/composer-git-hooks v2.6.0 requires php ^5.6 || >=7.0 <7.3 -> your PHP version (7.3.0) does not satisfy that requirement.
    
    opened by apertureless 11
  • Issue with multiline hook and &&

    Issue with multiline hook and &&

    Hi, I have the following script that checks that a commit message is formatted properly:

    {
      "prepare-commit-msg": [
          "CUR_BRANCH=\"$(git branch | grep '*' | sed 's/* //')\"",
          "if [ \"$CUR_BRANCH\" = '(no branch)' ]; then",
          "  exit 0",
          "fi",
          "COMMIT_REGEX='^(fixup! )*?(build|chore|ci|docs|feat|fix|perf|refactor|revert|style|test)(\\([a-z ]+\\))?: .+$'",
          "if ! grep -qE \"$COMMIT_REGEX\" \"$1\"; then",
          "  echo 'Invalid commit message, aborting... See https://github.com/pvdlg/conventional-changelog-metahub#commit-types' >&2",
          "  exit 1",
          "fi"
      ]
    }
    

    Since #106, multiline commands entries are now joined with && \. That brokes the bash script. As json doesn't allow multline strings, I don't see other way to write the script. I find convenient to write these little scripts in composer.json directly and not in separate script files.

    Any thoughts? Thanks

    opened by shaffe-fr 10
  • Bug: Windows - $'\r': command not found

    Bug: Windows - $'\r': command not found

    Commit failed - exit code 1 received, with output: '.git/hooks/pre-commit: line 2: $'\r': command not found
    committing as 
    /usr/bin/env: php: No such file or directory'
    

    When trying to commit via GitHub Desktop on Windows 10..

    This is what my composer.json looks like...

    "extra": {
        "laravel": {
            "dont-discover": []
        },
        "hooks": {
            "pre-commit": [
                "echo committing as $(git config user.name)",
                "vendor/bin/php-cs-fixer fix --using-cache=no ."
            ],
            "commit-msg": "grep -q '[A-Z]+-[0-9]+.*' $1",
            "pre-push": [
                "vendor/bin/php-cs-fixer fix --dry-run --using-cache=no .",
                "phpunit"
            ],
            "post-merge": "composer update"
        }
    },
    
    // ... some lines down
    
    "scripts": {
        "post-install-cmd": "cghooks add --ignore-lock",
        "post-update-cmd": "cghooks update",
    } 
    
    opened by Braunson 8
  • [Question] How about to add option for lock file path?

    [Question] How about to add option for lock file path?

    [Question] How about to add option for lock file path?

    Some projects has to have a lot of utility files like lock files and usually all of them are located in the project root. So why not to put cghooks.lock to some other place via cghooks binary option with project root by default?

    enhancement help wanted 
    opened by hanovruslan 8
  • Hooks are installed in a `--absolute-git-dir` directory

    Hooks are installed in a `--absolute-git-dir` directory

    My hooks are installed in a --absolute-git-dir directory ;)

    ls -al
    total 2055
    drwxrwxrwx 1 root root  12288 Jun 19 15:21 .
    drwxrwxrwx 1 root root   4096 Jun 19 11:50 ..
    drwxrwxrwx 1 root root      0 Jun 19 15:21 --absolute-git-dir
    drwxrwxrwx 1 root root      0 Jan 16 17:33 app
    [...]
    
    git --version
    git version 2.11.0
    
    git rev-parse --absolute-git-dir
    --absolute-git-dir
    

    It seems --absolute-git-dir was introduced in 2.13

    Originally posted by @Broutard in https://github.com/BrainMaestro/composer-git-hooks/pull/79#issuecomment-503562745

    opened by Broutard 8
  • Syntax error: word unexpected

    Syntax error: word unexpected

    Hi there! First of all: great tool! I love to keep the setup of repositories simple and having the ability to set up git hooks via composer is just great!

    I recently ran into this problem and can't seem to figure it out on my own. I did the following and got this error:

    $ vendor/bin/cghooks update
    : not foundcghooks: 2: vendor/bin/cghooks:
    : not foundcghooks: 4: vendor/bin/cghooks:
    vendor/bin/cghooks: 6: vendor/bin/cghooks: Syntax error: word unexpected (expecting "in")
    

    Any ideas? I don't really know what information can be useful so you'll have to tell me. Thanks!

    opened by ricardoboss 7
  • Your requirements could not be resolved to an installable set of packages.

    Your requirements could not be resolved to an installable set of packages.

    Your requirements could not be resolved to an installable set of packages.

    Problem 1 - brainmaestro/composer-git-hooks[v2.8.0, ..., v2.8.2] require symfony/console ^3.2 || ^4.0 -> found symfony/console[v3.2.0-BETA1, ..., 3.4.x-dev, v4.0.0-BETA1, ..., 4.4.x-dev] but the package is fixed to v6.1.5 (lock file version) by a partial update and that version does not match. Make sure you list it as an argument for the update command. - brainmaestro/composer-git-hooks[v2.8.3, ..., v2.8.5] require symfony/console ^3.2 || ^4.0 || ^5.0 -> found symfony/console[v3.2.0-BETA1, ..., 3.4.x-dev, v4.0.0-BETA1, ..., 4.4.x-dev, v5.0.0-BETA1, ..., 5.4.x-dev] but the package is fixed to v6.1.5 (lock file version) by a partial update and that version does not match. Make sure you list it as an argument for the update command. - Root composer.json requires brainmaestro/composer-git-hooks ^2.8 -> satisfiable by brainmaestro/composer-git-hooks[v2.8.0, ..., v2.8.5].

    Use the option --with-all-dependencies (-W) to allow upgrades, downgrades and removals for packages currently locked to specific versions. You can also try re-running composer require with an explicit version constraint, e.g. "composer require brainmaestro/composer-git-hooks:*" to figure out if any version is installable, or "composer require brainmaestro/composer-git-hooks:^2.1" if you know which you need.

    Installation failed, reverting ./composer.json and ./composer.lock to their original content.

    How can I solve this problem in laravel 9 and php 8?

    opened by j23063519 0
  • 3.0.0 stable tag

    3.0.0 stable tag

    Would it be possible to publish a stable tag for 3.0.0? Unfortunately this package is still broken with Symfony 6 if the projects minimum-stability is stable.

    opened by RaederDev 2
  • `stop-on-failure` has no effect

    `stop-on-failure` has no effect

    When the hook is a sequence of commands, execution is not stopped when the command fails.

    When the first command fails, it proceeds to the next command, and if the next command did not fail, completes the commit.

    image

    image

    opened by hmingv 0
  • Impossible to remove pre-commit hook?

    Impossible to remove pre-commit hook?

    Hi there,

    I changed a pre-commit hook to run on pre-push, ran cghooks update, but now the hook always runs on pre-commit.. All traces of pre-commit have been removed (composer.json, cghooks.lock) yet it still runs, even when opening new terminals.

    I'm out of options at this point except composer removing the dependency

    opened by webketje 2
Releases(v2.8.5)
  • v2.8.5(Feb 8, 2021)

  • v2.8.4(Jan 26, 2021)

    When generating a new hook, the commands are now concatenated with && to ensure that the each command is only executed if the preceding one returns a success (0) status code

    Source code(tar.gz)
    Source code(zip)
  • v2.8.2(Oct 17, 2019)

    • Older versions of git did not understand the git rev-parse --git-common-dir used to resolve the git dir, so a fallback was introduced.
    • The --ignore-lock modification was fixed, so there should be no issues for newcomers to an existing project anymore.

    Thanks to @devnix for pointing out these issues!

    Source code(tar.gz)
    Source code(zip)
  • v2.8.0(Sep 2, 2019)

    • git is now only invoked to resolve the git-dir if a --git-dir is not provided
    • --lock-dir was added which resolves to the current working directory if not provided
    Source code(tar.gz)
    Source code(zip)
  • v2.7.0(Jun 9, 2019)

    • Running cghooks in a git worktree now correctly resolves the .git folder.
    • cghooks is now aware of composer dev mode, and will not add or update hooks if run in production mode (--no-dev). This feature was REVERTED
    Source code(tar.gz)
    Source code(zip)
  • v2.6.0(Oct 28, 2018)

    All commands (besides the hook test ones) gained the ability to manage hooks globally with the --global option. Like:

    # Adds hooks in global directory (falls back to git config core.hooksPath and $COMPOSER_HOME)
    cghooks add --global 
    # You can also directly specify the directory
    cghooks add --global --git-dir /home/brainmaestro/.config/git_hooks
    

    The update, list-hooks and remove commands work similarly.

    This change was non-trivial because the application assumed it was always being run in the current directory. Took the opportunity for some cleanup as well.

    Source code(tar.gz)
    Source code(zip)
  • v2.5.0(Sep 2, 2018)

    For more complex hooks, they can be written as separate commands in an array. eg:

    "pre-commit": [
        "echo committing as $(git config user.name)",
        "php-cs-fixer .",
        "phpunit"
    ]
    
    Source code(tar.gz)
    Source code(zip)
  • v2.4.4(Jun 1, 2018)

Owner
Ezinwa Okpoechi
Ezinwa Okpoechi
A wrapper around symplify/config-transformer used to update recipes and using easy coding standard for generating readable config files.

Symfony Recipes Yaml to PHP Converter This is a wrapper around the symplify/config-transformer used to convert Symfony core recipes which uses .yaml c

Alexander Schranz 3 Nov 24, 2022
Some useful hooks desigend by DMIT for WHMCS

whmcs-hooks Some useful hooks desigend by DMIT for WHMCS CancelSubscription.php Cancel Subscriptions (like PayPal) when perform refund/cancel/change g

DMIT, Inc. 6 Dec 14, 2022
Hook-logger-plugin - Debug WordPress action / filter hooks.

hook-logger-plugin Easily debug WordPress action / filter hooks, finding where actions are called from and understanding the flow of execution. This p

bruce aldridge 4 Feb 5, 2022
A composer plugin, to install differenty types of composer packages in custom directories outside the default composer default installation path which is in the vendor folder.

composer-custom-directory-installer A composer plugin, to install differenty types of composer packages in custom directories outside the default comp

Mina Nabil Sami 136 Dec 30, 2022
Composer registry manager that help to easily switch to the composer repository you want

CRM - Composer Registry Manager Composer Registry Manager can help you easily and quickly switch between different composer repositories. 简体中文 Install

Tao 500 Dec 29, 2022
Private, self-hosted Composer/Satis repository with unlimited private and open-source packages and support for Git, Mercurial, and Subversion.

Private, self-hosted Composer/Satis repository with unlimited private and open-source packages and support for Git, Mercurial, and Subversion. HTTP API, HTTPs support, webhook handler, scheduled builds, Slack and HipChat integration.

Łukasz Lach 112 Nov 24, 2022
WordPress Packagist — manage your plugins with Composer

WordPress Packagist This is the repository for wpackagist.org which allows WordPress plugins and themes to be managed along with other dependencies us

Outlandish 648 Jan 1, 2023
Composer plugin that wraps all composer vendor packages inside your own namespace. Intended for WordPress plugins.

Imposter Plugin Composer plugin that wraps all composer vendor packages inside your own namespace. Intended for WordPress plugins. Built with ♥ by Typ

Typist Tech 127 Dec 17, 2022
Install an execute script of specify quality tools to your git pre-commit hook, and it executes only for changed files

Quality Hook Installer Install an execute script of specify quality tools to your git pre-commit hook, and it executes only for changed files Install

Kay W. 2 Dec 15, 2022
Ied plugin composer - Inspired Plugin Composer: Create, publish and edit plugins from within Textpattern CMS.

ied_plugin_composer Create, publish and edit plugins from within Textpattern CMS. Creates a new page under the Extensions tab where you can edit and e

Stef Dawson 8 Oct 3, 2020
Magento-composer-installer - Composer installer for Magento modules

!!! support the maintainer of this project via Patreon: https://www.patreon.com/Flyingmana Magento Composer Installer The purpose of this project is t

null 213 Sep 24, 2022
Composer Repository Manager for selling Magento 2 extension and offering composer installation for ordered packages.

Magento 2 Composer Repository Credits We got inspired by https://github.com/Genmato. Composer Repository for Magento 2 This extension works as a Magen

EAdesign 18 Dec 16, 2021
Dependency graph visualization for composer.json (PHP + Composer)

clue/graph-composer Graph visualization for your project's composer.json and its dependencies: Table of contents Usage graph-composer show graph-compo

Christian Lück 797 Jan 5, 2023
Composer Registrar Composer Plugin for Magento 2

This module add a global registration.php that replace the default glob search performed for each request to discover the components not installed from composer.

OpenGento 3 Mar 22, 2022
Drupal Composer Scaffold - A flexible Composer project scaffold builder

This project provides a composer plugin for placing scaffold files (like index.php, update.php, …) from the drupal/core project into their desired location inside the web root. Only individual files may be scaffolded with this plugin.

Drupal 44 Sep 22, 2022
Victor The Cleaner for Composer - This tool removes unnecessary files and directories from Composer vendor directory.

Victor The Cleaner for Composer This tool removes unnecessary files and directories from Composer vendor directory. The Cleaner leaves only directorie

David Grudl 133 Oct 26, 2022
Opinionated version of Wikimedia composer-merge-plugin to work in pair with Bamarni composer-bin-plugin.

Composer Inheritance Plugin Opinionated version of Wikimedia composer-merge-plugin to work in pair with bamarni/composer-bin-plugin. Usage If you are

Théo FIDRY 25 Dec 2, 2022
This module adds a command to easily generate "modules" in Laravel and install them using composer.

Laravel Module Create This module adds a command to easily generate "modules" in Laravel and install them using composer Installation Simply install t

null 2 Feb 18, 2022
Utility that helps you switch git configurations with ease.

git-profile Utility that helps you switch git configurations with ease Preface It is possible that you have multiple git configurations. For example:

Zeeshan Ahmad 240 Jul 18, 2022