Repository navigation
Add an update-strategy option for git sources - #223
Open
janwijbrand wants to merge 1 commit into
Open
janwijbrand wants to merge 1 commit into
janwijbrand wants to merge 1 commit into
Conversation
An existing checkout is reconciled with `git merge` and nothing else. So when the remote branch has been rebased and force-pushed, that merge brings back the commits the rewrite replaced and the run exits 0, with nothing reporting a problem. When the rewrite conflicts instead, the checkout is left mid-merge, with conflict markers written into the source files. Add `update-strategy`, settable per source or for the whole buildout: * `merge` -- the default, unchanged, so existing users see no difference; * `ff-only` -- only fast-forward, and report a rewritten branch together with the commands to recover from it; * `rebase` -- replay the local commits on top of the rewrite, leaving out the superseded copies of the commits it replaced, and abort without changing anything if one of them conflicts; * `reset` -- make the checkout match the remote branch exactly, for checkouts nobody edits by hand such as deployment hosts and CI. `rebase` leans on git rather than reimplementing it: `git rebase` already leaves out commits whose patch is upstream, which is exactly what the superseded copies are, and fast-forwards when there is nothing local to replay. Refs fschulze#82, which asked for rebase rather than merge as the default. This makes it an option instead, so nothing changes for anyone who does not ask for it. Alongside it, five smaller fixes that the same situation exposed: * report a checkout that is both ahead of and behind its remote as `diverged`, and one that is only behind as `behind`, instead of calling both `ahead`; * do not prompt "the package is dirty" when there is no terminal to answer it, which failed with a bare `EOFError` traceback; * name the state that actually blocked an update instead of always calling it dirty, since a branch that is merely ahead has a clean working tree; * name the revision, not a branch, when `git checkout` of a `rev` fails; * warn when a checkout is switched away from a branch that is not the configured one, instead of moving off it silently.
Owner
|
Sounds sensible and a very quick look at the changes didn't have anything jump out at me. So +1 from me. |
Author
Thanks - the next step is to merge it and release it? Can I help in anyway there? |
Author
|
Can I help in anyway there? |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The problem
git_updatereconciles an existing checkout withgit mergeand nothing else.When the remote branch has been rebased and force-pushed, that merge brings
back the commits the rewrite replaced — and buildout exits 0, so nothing
reports a problem:
Every commit now exists twice and the branch has silently diverged from its
remote. When the rewrite conflicts instead, the merge fails and the checkout is
left mid-merge, with conflict markers written into the source files.
This matters more than it used to: rebasing topic branches and GitHub's stacked
pull requests both rewrite published branches as a matter of course.
What this adds
An
update-strategyoption, settable per source or for the whole buildout:mergeff-onlyrebaseresetThe default stays
merge, so existing users see no change.rebaseleans on git rather than reimplementing it:git rebasealready leavesout commits whose patch is already upstream — which is exactly what the
superseded copies are — and fast-forwards when there is nothing local to
replay. On conflict the strategy runs
git rebase --abort, so a failed updatenever leaves a half-finished rebase behind.
resetis meant for checkouts nobody edits by hand: deployment hosts, CI andbuild images, where "make it match the remote" is the whole requirement.
Refs #82, which asked for rebase rather than merge as the default. This makes
it an option instead, so nothing changes for anyone who does not ask for it.
Also in here
Four smaller things the same investigation turned up, each with its own
changelog entry:
divergedrather thanahead, and one that is only behind asbehind.develop statusshows these asXand<. A rewritten remote branch waspreviously indistinguishable from having local commits.
always-checkoutset,a non-interactive run used to end in a bare
EOFErrortraceback frominput(); it now reports which checkout is in the way and what state it isin.
calling everything "dirty" — a branch that is merely ahead of its remote has
a perfectly clean working tree.
git checkoutof arevnames the revision, instead of a branchmasterthat was never involved.Testing
Eight new tests in
test_git.py, one per strategy plus the cases that are easyto get wrong: that
resetdiscards local commits when the checkout is ahead butnot behind, that a conflicting
rebaseleaves the checkout exactly as it was,and that
mergestill behaves as it always has.pre-commit run -apasses. The test suite passes locally except the mercurialand subversion tests, which need those binaries installed — CI does that.
Note
We have been running this internally as
3.0.0+md.1, built from this branch,while preparing the pull request.