git-assembler can perform automatic merge and rebase operations following a simple declarative script. Like “make”, for branches.
It can be used to follow remote branches (such as pull requests) conveniently, test multiple patches together, work on interdependent feature branches more easily, and so on…
Contents
Latest stable releases:
NEWS: | Summary of changes between releases. |
---|
All the relevant source/developer information including release notifications can be found on GitLab:
When working with git it’s often convenient/necessary to split development into separate branches, where each branch contains a logically independent set of changes. As time progresses though it’s not uncommon to work on several feature and bugfix branches at the same time, often long-lived, and with dependent or downright conflicting changes.
Managing such changes, keeping them separate and evolving them can become tedious and time consuming.
As an example, imagine working on a new feature on its own dedicated branch until a critical API is found to be missing, or broken. Policy dictates that such change needs a separate fix, so you split-off development into a dedicated branch and submit the change for testing. Meanwhile you go back to the feature branch, merge the fix, and continue. But the fix turns out to be incomplete a few days later, so you go back, commit, switch back and merge. At least once or twice more.
If that sounds familiar, and you’d like some automation, then a tool such as topgit or git-assembler might fit the bill. The major difference between the two is that topgit enforces a minimal workflow to preserve development history, while git-assembler just gives you the tools which could be used to implement such workflow, but enforces absolutely nothing.
You’ll need Python 3 and a recent version of Git (v2.23.0 or greater).
Copy git-assembler into $PATH:
git clone https://gitlab.com/wavexx/git-assembler cd git-assembler/ sudo cp git-assembler /usr/local/bin
Configure git:
git config --global alias.as assembler
git-assembler can now be invoked as:
git as
Without any argument, git as is a no-op and will show the current assembly status graph as defined from the .git/assembly file.
Scenario: You have a “fixes” branch which is where production bugs get fixed. You want to merge all “fixes” back to “master” unconditionally.
Create a test repository:
# a repository with a master branch git init touch file git add file git commit # create a "fixes" branch with a new commit git checkout -b fixes echo "test" > file git commit -a
Create .git/assembly with the following content:
merge master fixes
You can run git as --dry-run to display what git-assembler will do to update the repository:
$ git as --dry-run git-assembler: merging fixes into master
To show the current status in a graph, run git as with no flags:
$ git as master >fixes
“master” is shown followed with an indented list of branches to be merged (in this case only “fixes”). “master” is also shown either in bold or with the “~” suffix to indicate that it’s out of date. “fixes” is displayed in either green or with the “*” suffix to indicate that it contains updated content. The leading “>” indicates that it’s also the current branch.
To actually perform the merge use the --assemble/-a flag explicitly:
$ git as --assemble --verbose git-assembler: merging fixes into master git-assembler: restoring initial branch fixes
Scenario: You’re following a project “coolthing” with multiple forks. There are two PRs (“feature” from “user1” and “bugfixes” from “user2”) that interest you and want to always merge both into your own fork.
Clone the original project:
git clone https://github.com/coolthing/coolthing.git cd coolthing/
Add the two PRs, by adding the two remotes and fetching the respective branches:
git remote add user1 "https://github.com/user1/coolthing.git" git fetch user1 feature git remote add user2 "https://github.com/user2/coolthing.git" git fetch user2 bugfixes
Any valid ref name is allowed in .git/assembly, so we can directly reference them for any merge operation:
merge master origin/master merge master user1/feature merge master user2/bugfixes
Display the current status:
$ git as >master origin/masteruser1/feature user2/bugfixes
In this graph we see “master” is the current branch and is out-of-date (shown in bold or with “~”). “master” has three branches which are merged into it. “origin/master” is in sync (we just cloned from it), but “user1/feature” and “user2/bugfixes” (shown in green or with “*”) have more recent commits that need to be merged.
Use git as --dry-run (or -n in short) to see that broken down:
$ git as -n git-assembler: merging user1/feature into master git-assembler: merging user2/bugfixes into master
To perform the merges use git as -a.
To update your repository in the future you just need to fetch all remotes and then call git as -a. It’s usually convenient to display the current status with git as just prior to assembling:
# update from all sources git fetch --all # inspect the status git as # perform updates git as -a
It’s useless to call git pull in this scenario since git-assembler will do the same while also showing a more comprehensive repository status before performing the required merges. It isn’t forbidden though, and combining git pull with git as works just as well (it just takes more commands).
Scenario: You’re working on two independent feature branches (“feature1” and “feature2”) and want to keep both always rebased on “master” during development.
Create the following .git/assembly:
rebase feature1 master rebase feature2 master
The respective graph:
$ git as feature1 <-master feature2 <-master
The left arrow indicates that “feature1” is based on top of “master”.
Whenever master is updated (via git pull, for example), “master” will turn green to indicate new content, while both “feature1” and “feature2” become bold to indicate that they will be updated.
Running git as will rebase both in one shot, irregardless of the current branch:
$ git as -v git-assembler: rebasing feature1 onto master git-assembler: rebasing feature2 onto master
Scenario: You’re working on branch “feature”, but require “bugfix” for testing. You want to keep them logically separated, but still perform tests easily.
We can define a staging branch “test” with the following .git/assembly:
stage test feature merge test bugfix
A stage branch is recreated from scratch whenever it’s base or any of its merged branches is updated.
Resulting graph:
$ git as test <=feature bugfix
The left double arrow indicates that “test” is staged on top of “feature”. As seen before, it’s followed by a list of indented branches to merge: “bugfix”.
Whenever either “bugfix” or “feature” is updated, “test” is deleted and recreated first by branching off “feature” and then merging “bugfix”:
$ git as -av git-assembler: erasing existing branch test git-assembler: creating branch test from feature git-assembler: merging bugfix into test
Staging branches can be helpful also to ensure that branches merge cleanly.
git-assembler is best used with a short git alias (see Basic setup and Recommendations for extra details).
The suggested shorthand git as needs to be run within a git repository. The primary location of the configuration file is .git/assembly. Such file contains instructions on how to update any defined branches by performing merge or rebase operations. A complete list of commands is available in Assembly file reference.
By default, without any arguments, git-assembler reads the assembly file and displays a graph representation of the defined branches without performing any action:
$ cat .git/assembly merge master test $ git as master test
The graph layout is documented in Assembly graph reference.
The --dry-run/-n flag displays instead a flattened list of operations to be performed, in order, on the current repository:
$ git as --dry-run git-assembler: merging test into master
To actually perform the operations the --assemble/-a flag is always required. This is true also for the --create or --recreate flags. This can be seen in conjunction with --dry-run:
$ cat .git/assembly base new master merge new bugfix $ git as --dry-run git-assembler: branch new needs creation from master $ git as --dry-run --create git-assembler: creating branch new from master git-assembler: merging bugfix into new
By default all defined branches are either displayed or updated. A list of explicit targets can be given on the command line:
$ cat .git/assembly merge branch1 a b merge branch2 c $ git as branch1 a b branch2 c $ git as branch2 branch2 c $ git as -av branch2 git-assembler: merging c into branch2
When working on large projects the list of default targets can be overridden in the assembly file. Non-existent branches are ignored unless they are depended-on by one of the requested targets. Branches which exist, but are not defined, are also ignored.
There’s no magic introduced by git-assembler involving conflicts.
When conflicts arise in a merge operation git-assembler will drop you into the branch which is being merged onto. Assuming a simple merge conflict:
$ cat .git/assembly merge master branch1 $ git as -av git-assembler: merging branch1 into master Auto-merging test CONFLICT (content): Merge conflict in test Recorded preimage for 'test' Automatic merge failed; fix conflicts and then commit the result. U test git-assembler: error while merging branch1 into master git-assembler: stopping at branch master, fix/commit then re-run git-assembler
Use git add/commit as usual to resolve the conflict, or git merge --abort to cancel the merge. Aborting the merge can be useful, for example, to invoke a different merge strategy or to remove the offending rule and disregard the merge completely.
As soon as the merge is resolved or aborted, state is instantly reflected into git as:
# fix the merge $ git commit $ git as -av git-assembler: already up to date
Of course, if the merge is aborted but the merge rule is not removed, git as will simply try again on the next invocation.
Additional information is displayed when two or more branches are involved in the current run:
$ cat .git/assembly merge master branch1 merge branch1 branch2 $ git as >master branch1 branch2 $ git as -av git-assembler: merging branch2 into branch1 Auto-merging test CONFLICT (content): Merge conflict in test Recorded preimage for 'test' Automatic merge failed; fix conflicts and then commit the result. U test git-assembler: error while merging branch2 into branch1 git-assembler: stopping at branch branch1, fix/commit then re-run git-assembler
“master” will be adorned in the graph to indicate that it was the initial branch when git as was started (note the “<” before the name), while the current branch you’re now on is “branch1”:
$ git as <master >branch1branch2
After fixing the merge, running git as -av a second time will continue and restore the initial branch:
# fix conflict $ git commit $ git as -av git-assembler: merging branch1 into master git-assembler: restoring initial branch master
Conflicts arising during a rebase operation drop you on the branch which is being rebased and work exactly the same: just fix the conflict and either rebase --continue or rebase --abort as you normally would.
The situation gets more complex when stage (and, to a lesser extent, base) is involved somewhere in the graph.
Since staging branches will be deleted and re-created at every update, the same merge conflicts will keep repeating unless the conflict is handled within the branch being merged itself, which is not always desired.
In these situations git-rerere is required (see Recommendations).
The basic gist of rerere is that, once enabled, will record how the conflict was resolved and apply the same solution whenever it happens again. This allows the same merge operation to repeat successfully.
git as applies merges in a deterministic order (the declaration order) in order to let you control and maximize the chances of a successful and reproducible resolution. git as will additionally auto-commit a successful rerere solution so that the operation can continue without manual intervention in most cases.
git rerere might lead to surprising (and sometimes broken) results during conflict resolution, which is the main reason it’s not enabled by default. Reading rerere‘s own documentation and experimenting on a toy repository is highly encouraged before starting to use staging branches.
The .git/assembly file is not set in stone. Change and adapt your rules to whatever makes you work better. The --edit command line flag offers a convenient way to do that. I adapt my rules according to what branches I’m working on and remove them when I’m done.
Also, just because you can rebase everything, it doesn’t mean you should. Pushed-state aside, you can still work with plain merges and rebase just once for cleanup. Or mix the two methods by intervening manually.
In contrast to other similar tools, git-assembler is stateless and doesn’t care what you do or did to get to the current repository state.
Not all branch layouts that can be defined with git-assembler make sense (or work at all).
Scenario: You have a “feature” branch and you want to keep an ephemeral branch “test” where changes from both mainline and the feature branch are continuously merged. Using stage would work, but cause the work tree to change and rebuild too frequently. You need something more efficient.
A simple and perfectly valid approach would be to just create a throw-away branch and use merge:
git checkout -b test master
.git/assembly:
merge test master feature
You can more conveniently mark that “test” can be bootstrapped from “master” using the base command:
base test master merge test master feature
The graph shows:
$ git astest ..master master feature
The “..” notation indicates that “test” is initially based off “master”. Also, the first time git as is run, “test” is highlighted in red or with the “?” suffix to indicate that the branch doesn’t exist. “base” branches are not initialized unless --create is given on the command line:
$ git as -av git-assembler: branch test needs creation from master $ git as -avc git-assembler: creating branch test from master git-assembler: merging master into test git-assembler: merging feature into test git-assembler: restoring initial branch master
Any subsequent update would simply perform the merge operations as needed. But, because “base” branches are intended to be ephemeral, they can also be explicitly re-initialized to discard any branch history and start anew by using --recreate:
$ git as -av --recreate git-assembler: erasing existing branch test git-assembler: creating branch test from master git-assembler: merging master into test git-assembler: merging feature into test git-assembler: restoring initial branch master
Base branches behave otherwise like a normal branch: if you want to update from the starting branch you have to do so explicitly, as done above.
Scenario: You’re working on branch “feature”, but require “bugfix” to continue development, as well as recent changes from “master” (“bugfix” is too old, and is still in development). You want to keep “feature“‘s history clean during development, before it’s being pushed.
We can use an intermediate branch with both master and “bugfix” applied. Then rebase our “feature” branch on top of it:
base temp master merge temp master merge temp bugfix rebase feature temp
The resulting graph:
feature <- [temp]temp ..master master bugfix
This is efficient, but what if “bugfix” inadvertently gets rebased? Bootstrap the “temp” branch again, using git as -a --recreate.
If “bugfix” happens to rebase frequently then a staging branch can get more verbose (requiring rerere to be active), but will keep on working:
stage temp master merge temp bugfix rebase feature temp
The graph is similar:
feature <- [temp] temp <=master bugfix
Once bugfix is applied, we can just discard our temporary branch and rebase on “master”.
Scenario: a repository has a consistent branch naming scheme where all patches to be applied on the master branch start with a pre-determined prefix. You want to merge all these branches back to your “testing” branch for early assessment without having to list them manually.
You can use wildcards in all branch names to automatically expand to the known list of branches, either local or remote. For example, assuming the fix_ prefix is used consistently by your team for patches going to the master branch, you do the following:
stage testing upstream/master merge testing upstream/fix_*
to have a “testing” branch which contains continuously all unmerged fixes for you to play with. The graph will show the expanded list of available branches:
$ git fetch upstream $ git as testing testing <=upstream/master fix_bug fix_version_number
Wildcards can be used as the target of a rule. This allows a single rule to operate on multiple branches at once. For example, to rebase all dev_ branches to the current master you can:
rebase dev_* upstream/master
You can also furthermore limit the scope of your actions by providing a wildcard pattern on the command line as well:
$ git as -av 'dev_feat_*' git-assembler: rebasing dev_feat_1 onto upstream/master git-assembler: rebasing dev_feat_2 onto upstream/master
Regular expressions are available for more complicated naming schemes (see Wildcard patterns).
Scenario: you’re working on a fix and want to continuously test/rebuild the changes on two different mainlines: stable and development.
Worktrees allow to keep multiple checked-out copies of the same repository, with each tree pointing to a different branch. git-assembler will correctly update any branch which is checked-out in the appropriate tree, keeping it always up-to-date.
Assuming “stable” and “development” are related, you can start working on a “bugfix” branch:
git clone git://host/repository development cd development git checkout -b bugfix # ... do some development ... git commit
then define a staging branch “stable-test” where “bugfix” is applied, using the following assembly file:
stage stable-test stable merge stable-test bugfix
Run git as -a once to first construct the branch, then checkout for testing on a different worktree:
$ git worktree add ../testing stable-test
The assembly graph immediately shows that “stable-test” is checked-out in ../testing after the branch name:
$ git as stable-test(../testing ) <= stable bugfix
You can now keep working on the “development” branch as usual. Whenever you want to check if your patch still applies and works correctly on the stable branch, you can re-run git as -a to refresh both your branch and your ../testing tree.
git-assembler makes no distinction between the main repository’s working-copy and other worktrees. They’re all equivalent. The worktree path is shown only when necessary, and it’s always relative to the current worktree.
When a temporary branch needs to be checked-out, the current tree is used to perform the temporary work. This means that during an interrupted operation (typically a conflict), the current tree will also be the tree being affected unless the offending branch is already checked out in another worktree. In such cases git-assembler will always indicate that the operation needs to be completed in another tree:
$ git as -v git-assembler: error while merging bugfix into stable-test(../testing) git-assembler: stopping at branch stable-test in ../testing git-assembler: fix/commit then re-run git-assembler
The operation can be resumed from any worktree, but the tree used for temporary work will remain fixed until the entire assembly operation is successful. Upon completion, the initial branch<>tree state is restored.
Merge and rebase operations can be customized at a lower-level by providing git command-line flags directly. These can be used to control if a merge is allowed to fast-forward or to change the merge/resolution strategy being used, either by default or on a branch-by-branch basis.
Git flags can be specified in both merge and rebase commands immediately after the branch list by starting with a dash.
For example, assuming we’re merging an “obsolete” branch into “master” and want to handle conflicts by just replacing all hunks with newer code, we can use the “ours” merge strategy as follows:
merge master obsolete -s ours
When multiple branches are used on the same rule, flags are applied to all branches in the rule. For example:
merge master branch1 branch2 -s ours
is equivalent to:
merge master branch1 -s ours merge master branch2 -s ours
Default flags can be set for all merge/rebase operations by using the flags command, which applies for all subsequent merge/rebase operations.
This can be used to set the default merge fast-forward settings in alternative to assembler.mergeff:
flags merge --ff merge master branch
Each flags command replaces the previous flags. The following assembly file:
flags merge --ff merge master branch1 flags merge --no-ff merge master branch2
is equivalent to:
merge master branch1 --ff merge master branch2 --no-ff
Flags specified in a merge/rebase rule are appended to the default flags, allowing a rule to override previous settings:
flags merge --ff # set --ff for next merge commands merge master branch1 # --ff is set by default merge master branch2 --no-ff # --no-ff overrides the default
Care should be taken when specifying flags. It’s not currently possible to use flags that alter the expected base/target branch of the operation as this would break the internal dependency graph. One notable example is attempting to use rebase --onto: https://gitlab.com/wavexx/git-assembler/-/issues/18
It’s possible to see the full git command line as executed by increasing verbosity:
$ git as -avvv git-assembler: reading instructions from .gitassembly git-assembler: merging branch into master using --ff git-assembler: running cwd=/tmp git merge -q --rerere-autoupdate --no-edit --ff branch
The graph takes the following core structure:
branch bases dependencies
The branch is followed on the right with a list of the base branches (with annotations) and an indented list of dependencies (branches) to merge.
Such structure can nest:
branch branch dependencies branch branch <- base .. base ...
Bases will be split off into a separate root when they also contain dependencies that cannot be represented compactly. The branch is adorned with [brackets] when this happens to indicate an indirect node:
branch <- [base]
Depending whether the current terminal supports colors, branches can be highlighted or suffixed with the following:
Suffix | Color | Meaning |
---|---|---|
branch? | Red | Branch is missing or non-existent |
branch~ | Bold | Branch needs to be updated |
branch* | Green | Branch contains updated content |
Branches can also be prefixed with:
Prefix | Meaning |
---|---|
>branch | Branch is the current branch |
<branch | Branch was the initial branch when git-assembler was called and interrupted before finishing |
Each branch can be immediately followed by (worktree path) if the current directory is not inside the tree itself. Assuming we’re on the master branch and branch2 is checked-out in a separated worktree, the graph will show:
>master branch2(../worktree )
The opposite is true if the current working directory is inside the branch2 worktree:
master(../project ) >branch2
branch merge ...
merge are branches which get merged into branch whenever they’re newer, and can be added using the merge command. The list of merged branches follows the final merge order. branch is a regular branch, unless followed by other symbols.
branch <- base
branch is rebased on top of base when base is updated. It is generated by the rebase command.
branch .. base
branch can be bootstrapped or re-created on top of base. Generated by the base command.
branch <= base merge
branch is deleted and re-created on top of base whenever either base or merge is newer. Generated by the stage command.
branch definition master <- [branch]
[branch] refers to a branch defined elsewhere in the graph.
The assembly file is searched in the following order:
$GIT_DIR/.git/assembly $GIT_DIR/.gitassembly
.git/assembly is local and overrides a possibly versioned .gitassembly. The location can be overridden on the command line through the --config flag.
Empty lines and lines starting with “#” are ignored. Leading and trailing whitespace is also ignored, allowing both commands and comments to be indented. Each command starts on it’s own line.
Commands that define a branch type (base, stage, rebase) cannot be specified more than once per target. Ordering is only relevant for the merge command.
The “base” of any rule (the third argument of base, stage or rebase) can be any valid git refspec. This is normally a naked branch name, but it can be a fully qualified branch name (such as remote/branch), any valid commit hash or a commit-ish. The base cannot be a wildcard.
Syntax: | target branch [branch...] |
---|---|
Description: | Set the default target branch (or branches) to operate on when no explicit branch is given on the command line. Each branch can be a wildcard. When no target is specified, all defined branches are checked for updates. Use --all on the command line to override the default target. target can be specified only once. |
Syntax: | base branch-name base-name |
---|---|
Description: | Define branch-name to be a “regular” branch which can be optionally bootstrapped from base-name. branch-name can optionally be a wildcard, resulting in rule expansion. base-name can be any valid refspec, commit hash or commit-ish. If branch-name doesn’t exist and --create is specified on the command line then branch-name is forked off base-name. When --recreate is given, branch-name is deleted and recreated, discarding any existing commit. |
Syntax: | stage branch-name base-name |
---|---|
Description: | Define branch-name to be a “staging” branch which is deleted and recreated by forking off base-name every time any of its dependencies (base or merged branches) are updated. branch-name can optionally be a wildcard, resulting in rule expansion. base-name can be any valid refspec, commit hash or commit-ish. |
Syntax: | rebase branch-name base-name [git rebase flags] |
---|---|
Description: | Define branch-name to be a “rebased” branch. Rebase branch-name on top of base-name every time base-name is updated. branch-name can optionally be a wildcard, resulting in rule expansion. base-name can be any valid refspec, commit hash or commit-ish. Rebase command line flags can be directly specified after the base. Flags are recognized by starting with a dash. They are appended to the current global flags (see flags) when running the underlying rebase command, allowing to override the global behavior. |
Syntax: | merge target branch [branch...] [git merge flags] |
---|---|
Description: | Merge branch into target every time branch is updated. Multiple branches to merge can be given on the same command, they’re equivalent to multiple merge rules. merge can be repeated to specify more branches on multiple lines. The merge order follows the declaration order. target can optionally be a wildcard, resulting in rule expansion. Each branch can also be a wildcard where duplicates in the resulting branch list are ignored. Merge command line flags can be directly specified after the branch/es. Flags are recognized by starting with a dash. The flags apply to all the branches specified in the current rule. They are appended to the current global flags (see flags) and to the current assembler.mergeff settings when running the underlying merge command, allowing to override the global behavior. |
Limitations: | merge never performs multi-head merges: each branch is merged individually. It’s not currently possible to perform a rebase --onto operation, even with custom flags: https://gitlab.com/wavexx/git-assembler/-/issues/18 |
Syntax: | flags (merge|rebase) [git flags] |
---|---|
Description: | Set the default git command line flags for all future merge or rebase commands. Each flags command replaces the previous flags. When no flags are specified, the list is reset to empty (the default). Each merge or rebase command can specify further flags that are appended to this list to override the behavior on a branch-by-branch basis. The flags are used during the underlying git invocation, allowing to change low-level behavior such as the merge strategy, fast-forward settings and more (see Customizing merge and rebase behavior). |
git-assembler-mode is an Emacs major-mode to edit assembly files. Available through Melpa.
Branch operands (any argument of target/merge or the second argument of base, stage or rebase) can contain wildcards.
A wildcard can be either a glob-like pattern or a regular expression (see Wildcard patterns). Wilcard expansion is performed early, and will not match branches created as a side-effect of the assembly process.
A wildcard in the target of a rule will expand to multiple rules having the same arguments. In a repository containing the branches fix_a and fix_b, the rule:
rebase fix_* upstream/master
will expand to:
rebase fix_a upstream/master rebase fix_b upstream/master
A wildcard elsewhere will simply expand to the list of matches:
merge master fix_*
which results in:
merge master fix_a fix_b
An expansion is required to produce at least one branch to ensure that each produced rule is not superfluous. An expansion also cannot override any previously-defined rule. As an exception, branch names expanded in merge arguments are silently ignored to allow controlling dependency order in combination with wildcards. The following rule:
merge master fix_b fix_*
is accepted, pre-pending fix_b before the expansion (despite the implicit duplicate fix_b) branch and resulting in just:
merge master fix_b fix_a
This silent behavior can be seen by increasing verbosity.
Wilcard patterns are glob-like by default, unless prefixed by a forward slash.
In a glob-like pattern, a single * will expand to the current list of branches in the current namespace and will stop and the first /. A ** instead will match anything.
For example, given the following branch list:
the pattern upstream* will only match upstream_fixes, while upstream** also includes upstream/fix_*.
Both pattern forms will match a zero-length substring.
If a wildcard starts with the forward slash character / it is interpreted as a non-anchored extended regular expression. The first / itself is dropped and is not part of the expression. A final forward slash though is significant (it is not interpreted as the end of the search pattern).
Here are some glob/regex equivalences to illustrate the difference:
glob | regex |
---|---|
master | /^master$ |
upstream* | /^upstream[^/]*$ |
upstream** | /^upstream |
upstream/** | /^upstream/ |
**/fix_* | //fix_[^/]*$ |
Regular expression patterns can’t contain spaces. See Python’s RE module documentation for the full supported expression reference.
It is possible to configure git-assembler‘s behavior via git config or environment variables. Below is a reference of the supported configuration keys. Environment variables override values possibly set with git config.
Key: | assembler.mergeff |
---|---|
Env variable: | GIT_ASSEMBLER_MERGEFF |
Possible Values: | |
true, false (or any boolean value accepted by git config) or empty/unset | |
Default: | unset |
Description: | If true, instructs git-assembler to use the flag --ff when doing merges. If false, the flag --no-ff is used instead. When empty/unset (the default), no additional flags are passed and merges follow git’s defaults. |
Once git-assembler is installed, it can be called as a regular git sub-command:
git assembler
We recommend to define a shorter global alias:
git config --global alias.as assembler
which allows to use git-assembler using just:
git as
Since git-assembler can be instructed to perform the same merge and rebase operations over and over, it is recommended to enable rerere in each repository where git-assembler is being used:
# enable in the current repository only git config rerere.enabled true # or enable for all repositories git config --global rerere.enabled true
Good familiarity with git-rerere is recommended.
Ensure the git reflog (core.logAllRefUpdates) has not been disabled. It is essential for the correct operation of non-trivial rebase operations.
git-assembler‘s GIT repository is publicly accessible at: