* [RFC PATCH] Documentation: new upstream rebase recovery section in git-rebase @ 2008-09-02 20:18 Thomas Rast 2008-09-02 21:39 ` Junio C Hamano 2008-09-08 22:55 ` [RFC PATCH] Documentation: new upstream rebase recovery section in git-rebase Junio C Hamano 0 siblings, 2 replies; 29+ messages in thread From: Thomas Rast @ 2008-09-02 20:18 UTC (permalink / raw) To: git Documents how to recover if the upstream that you pull from has rebased the branches you depend your work on. Hopefully this can also serve as a warning to potential rebasers. Signed-off-by: Thomas Rast <trast@student.ethz.ch> --- I've always found the "warning" on the git-rebase manpage (it's not even marked as a warning!) a bit weak. So this is an attempt to solve two problems in one go. It should be precise enough to help users understand and recover, but scary enough to prevent them from doing such rebases in the first place. I flagged it as RFC because I'd appreciate some feedback: - Are the warnings too repetitive? I fear that if we sound too protective, users won't listen. - Is it perhaps too verbose, or in the wrong place? I did not want to detract from the feature descriptions that the manpage should first and foremost contain. Chances that a user will "accidentally" read the section at this position and length seem fairly low however. I've also edited it a fair bit, so chances are that mistakes have snuck in. If you like the general direction of this, I'll also make a patch that points at this section from other rewriting manpages. - Thomas Documentation/git-rebase.txt | 79 +++++++++++++++++++++++++++++++++++++++-- 1 files changed, 75 insertions(+), 4 deletions(-) diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt index 59c1b02..5e1dc30 100644 --- a/Documentation/git-rebase.txt +++ b/Documentation/git-rebase.txt @@ -257,11 +257,12 @@ include::merge-strategies.txt[] NOTES ----- -When you rebase a branch, you are changing its history in a way that -will cause problems for anyone who already has a copy of the branch -in their repository and tries to pull updates from you. You should + +As a rule of thumb, rebasing anything that you have published already +is a bad idea. It causes problems for people who already have a copy +of your branch, and are trying to pull updates from you. You should understand the implications of using 'git-rebase' on a repository that -you share. +you share. See also HELP, MY UPSTREAM HAS REBASED! below. When the git-rebase command is run, it will first execute a "pre-rebase" hook if one exists. You can use this hook to do sanity checks and @@ -396,6 +397,76 @@ consistent (they compile, pass the testsuite, etc.) you should use after each commit, test, and amend the commit if fixes are necessary. +HELP, MY UPSTREAM HAS REBASED! +------------------------------ + +This section briefly explains the problems that arise from rebasing +published branches, and shows how to recover. The process is rather +tedious, so we emphasize again: 'Avoid rebasing published branches.' +(The same warning goes for other history rewriting too, for example, +`git commit --amend` and 'git-filter-branch'.) + +To illustrate, suppose you are in a situation where someone develops a +'subsystem' branch, and you are working on a 'topic' that is dependent +on this 'subsystem'. You might end up with a history like the +following: + +------------ + o---o---o---o---o master + \ + o---o---o---o---o subsystem + \ + *---*---* topic +------------ + +In a push/pull workflow, the maintainer of 'subsystem' would use `git +merge master` to grab updates from upstream, and you can use the +analogous `git merge subsystem`. + +If 'subsystem' is instead **rebased** against master, the following +happens: + +------------ + o---o---o---o---o master + | \ + | o'--o'--o'--o'--o' subsystem + \ + o---o---o---o---o---*---*---* topic +------------ + +Note that while we have marked your own commits with a '*', there is +nothing that distinguishes them from the commits that previously were +on 'subsystem'. You can easily verify this with, for example, `git +log subsystem..topic` -- which returned only your own commits in the +scenario of the first graph above, but now has all the commits of the +old 'subsystem' too! Furthermore, a potential merge of 'topic' into +'subsystem' is liable to cause unnecessary conflicts due to the +duplicated changes. + +To recover from this, you need to find the original branch point +manually, and rebase your topic against the new 'subsystem'. Since in +the graph, there are 3 commits that were your own, you can do +------------ + git rebase --onto subsystem HEAD~3 topic +------------ +and end up with the fixed history +------------ + o---o---o---o---o master + \ + o'--o'--o'--o'--o' subsystem + \ + *'--*'--*' topic +------------ + +`git pull --rebase` (see linkgit:git-pull[1]) can be used to automate +this process, but only if you use it instead of fetching, so that it +can use the old upstream head to determine the previous branch point. + +The rewriting becomes a ripple effect to developers downstream from +you (if any): since you now have rebased 'topic', they will have to +manually rebase their own work to reflect this! + + Authors ------ Written by Junio C Hamano <gitster@pobox.com> and -- 1.6.0.1.302.g47141 ^ permalink raw reply related [flat|nested] 29+ messages in thread
* Re: [RFC PATCH] Documentation: new upstream rebase recovery section in git-rebase 2008-09-02 20:18 [RFC PATCH] Documentation: new upstream rebase recovery section in git-rebase Thomas Rast @ 2008-09-02 21:39 ` Junio C Hamano 2008-09-03 5:38 ` Thomas Rast 2008-09-08 22:55 ` [RFC PATCH] Documentation: new upstream rebase recovery section in git-rebase Junio C Hamano 1 sibling, 1 reply; 29+ messages in thread From: Junio C Hamano @ 2008-09-02 21:39 UTC (permalink / raw) To: Thomas Rast; +Cc: git Thomas Rast <trast@student.ethz.ch> writes: > I flagged it as RFC because I'd appreciate some feedback: > > - Are the warnings too repetitive? I fear that if we sound too > protective, users won't listen. > > - Is it perhaps too verbose, or in the wrong place? I did not want to > detract from the feature descriptions that the manpage should first > and foremost contain. Chances that a user will "accidentally" read > the section at this position and length seem fairly low however. It feels on a bit too repetitive side, but I think this is going in the right direction. How about dropping the earlier part of the change to Notes section (but keep "See also" which is a good guide for understanding the said "implications")? > +HELP, MY UPSTREAM HAS REBASED! > +------------------------------ I read this section only once, but it looked reasonable as a recovery procedure to me. The additions you made are all about why rebasing public history is bad from mechanisms (overlapping changes made by old upstream history and new upstream history, unless they are identical, will cause merge conflicts between themselves that downstream will have hard time resolving) POV. While that description is all good, I think there should also be a discussion from the patchflow/workflow angle. "Upstream has rebased" almost implies that it has its own upstream (i.e. "My upstream" is not the toplevel upstream, but is a subsystem tree or something). Rebasing upstream is bad, but an upstream that backmerges from its own upstream too often is equally bad, and the reason of the badness, viewed from the workflow angle, shares exactly the same component. It means that the mid-level upstream in question is not focused enough. Cf. http://article.gmane.org/gmane.linux.kernel/681763 http://article.gmane.org/gmane.linux.kernel/684030 http://article.gmane.org/gmane.linux.kernel/684073 http://article.gmane.org/gmane.linux.kernel/684091 http://article.gmane.org/gmane.linux.kernel/638511 ^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [RFC PATCH] Documentation: new upstream rebase recovery section in git-rebase 2008-09-02 21:39 ` Junio C Hamano @ 2008-09-03 5:38 ` Thomas Rast 2008-09-11 15:38 ` [PATCH 0/2.5] " Thomas Rast 0 siblings, 1 reply; 29+ messages in thread From: Thomas Rast @ 2008-09-03 5:38 UTC (permalink / raw) To: git; +Cc: Junio C Hamano [-- Attachment #1: Type: text/plain, Size: 688 bytes --] Junio C Hamano wrote: > Thomas Rast <trast@student.ethz.ch> writes: > > +HELP, MY UPSTREAM HAS REBASED! > > +------------------------------ > > I read this section only once, but it looked reasonable as a recovery > procedure to me. Thanks a lot for your comments, I will look into the links you gave me. It occured to me that rebase's ability to skip existing commits can effectively replace the entire manual component of finding out when the topic branch started. Which makes it far less scary. :-( Maybe I'll write something about editing with 'rebase -i' instead, which breaks the automatic skips again. - Thomas -- Thomas Rast trast@student.ethz.ch [-- Attachment #2: This is a digitally signed message part. --] [-- Type: application/pgp-signature, Size: 197 bytes --] ^ permalink raw reply [flat|nested] 29+ messages in thread
* [PATCH 0/2.5] Documentation: new upstream rebase recovery section in git-rebase 2008-09-03 5:38 ` Thomas Rast @ 2008-09-11 15:38 ` Thomas Rast 2008-09-11 15:38 ` [PATCH 1/2] " Thomas Rast 0 siblings, 1 reply; 29+ messages in thread From: Thomas Rast @ 2008-09-11 15:38 UTC (permalink / raw) To: git; +Cc: Junio C Hamano So here's the follow-up I promised. Junio C Hamano <gitster@pobox.com> wrote: > > Thomas Rast <trast@student.ethz.ch> writes: > > - Is it perhaps too verbose, or in the wrong place? I did not want to > > detract from the feature descriptions that the manpage should first > > and foremost contain. Chances that a user will "accidentally" read > > the section at this position and length seem fairly low however. > > It feels on a bit too repetitive side, but I think this is going in the > right direction. How about dropping the earlier part of the change to > Notes section (but keep "See also" which is a good guide for understanding > the said "implications")? I rewrote it to include the actual rebase behaviour and some scenarios that arise from 'rebase -i', 'commit --amend' etc., then tried to shorten the section as far as I could. Hopefully this cut down on the repetitions. Unfortunately it still grew longer due to the extra content. The second patch then includes references to that section in the appropriate manpages. The third patch is again RFC, and I made it regarding this section: > The additions you made are all about why rebasing public history is bad > from mechanisms [...] POV. > While that description is all good, I think there should also be a > discussion from the patchflow/workflow angle. > > "Upstream has rebased" almost implies that it has its own upstream > (i.e. "My upstream" is not the toplevel upstream, but is a subsystem tree > or something). > > Rebasing upstream is bad, but an upstream that backmerges from its own > upstream too often is equally bad, and the reason of the badness, viewed > from the workflow angle, shares exactly the same component. > > It means that the mid-level upstream in question is not focused enough. I noticed that there is no manpage in which we document such workflows anyway. There is a short definition of 'topic branch' in glossary-content.txt, and a parenthetical definition in user-manual.txt in a sort of "linux.git howto". Nothing longer, however. [I learned what I know from Linus's Google Tech Talk[1], Tv's more recent EuroPython talk[2], looking at git.git, and mail such as the ones you linked. I recommended [2] to people who asked about topic branches on #git a few times.] So this is an attempt to make a "workflow reference". I tried to strike a balance between "just" a reference (the Rule/Recipe blocks) and more of a tutorial approach which explains the reasons. I would again greatly appreciate comments. - Thomas Thomas Rast (2+1): Documentation: new upstream rebase recovery section in git-rebase Documentation: Refer to git-rebase(1) to warn against rewriting Documentation: add manpage about workflows [1] http://video.google.com/videoplay?docid=-2199332044603874737 [2] http://blip.tv/file/1114793/ ^ permalink raw reply [flat|nested] 29+ messages in thread
* [PATCH 1/2] Documentation: new upstream rebase recovery section in git-rebase 2008-09-11 15:38 ` [PATCH 0/2.5] " Thomas Rast @ 2008-09-11 15:38 ` Thomas Rast 2008-09-11 15:38 ` [PATCH 2/2] Documentation: Refer to git-rebase(1) to warn against rewriting Thomas Rast ` (2 more replies) 0 siblings, 3 replies; 29+ messages in thread From: Thomas Rast @ 2008-09-11 15:38 UTC (permalink / raw) To: git; +Cc: Junio C Hamano Documents how to recover if the upstream that you pull from has rebased the branches you depend your work on. Hopefully this can also serve as a warning to potential rebasers. Signed-off-by: Thomas Rast <trast@student.ethz.ch> --- Documentation/git-rebase.txt | 103 +++++++++++++++++++++++++++++++++++++++-- 1 files changed, 98 insertions(+), 5 deletions(-) diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt index 59c1b02..ba5255d 100644 --- a/Documentation/git-rebase.txt +++ b/Documentation/git-rebase.txt @@ -257,11 +257,10 @@ include::merge-strategies.txt[] NOTES ----- -When you rebase a branch, you are changing its history in a way that -will cause problems for anyone who already has a copy of the branch -in their repository and tries to pull updates from you. You should -understand the implications of using 'git-rebase' on a repository that -you share. + +You should understand the implications of using 'git-rebase' on a +repository that you share. See also RECOVERING FROM UPSTREAM REBASE +below. When the git-rebase command is run, it will first execute a "pre-rebase" hook if one exists. You can use this hook to do sanity checks and @@ -396,6 +395,100 @@ consistent (they compile, pass the testsuite, etc.) you should use after each commit, test, and amend the commit if fixes are necessary. +RECOVERING FROM UPSTREAM REBASE +------------------------------- + +This section briefly explains the problems that arise from rebasing or +rewriting published branches, and shows how to recover. As you will +see, the process is rather tedious, so we emphasize again: 'Avoid +rewriting published history.' This goes for `rebase`, `commit +--amend`, `reset HEAD^` and `filter-branch` alike. + +To illustrate, suppose you are in a situation where someone develops a +'subsystem' branch, and you are working on a 'topic' that is dependent +on this 'subsystem'. You might end up with a history like the +following: + +------------ + o---o---o---o---o master + \ + o---o---o---o---o subsystem + \ + *---*---* topic +------------ + +If 'subsystem' is rebased against master, the following happens: + +------------ + o---o---o---o---o master + | \ + | o'--o'--o'--o'--o' subsystem + \ + o---o---o---o---o---*---*---* topic +------------ + +Note that while we have marked your own commits with a '*', there is +nothing that distinguishes them from the commits that previously were +on 'subsystem'. Luckily, 'git-rebase' knows to skip commits that are +textually the same as commits in the upstream. So if you say +(assuming you're on 'topic') +------------ + git rebase subsystem +------------ +you will end up with the fixed history +------------ + o---o---o---o---o master + \ + o'--o'--o'--o'--o' subsystem + \ + *'--*'--*' topic +------------ + +This becomes a ripple effect to anyone downstream of the first rebase: +anyone downstream from 'topic' now needs to rebase too, and so on. + +Things get more complicated if your upstream used `git rebase +--interactive` (or `commit --amend` or `reset --hard HEAD^`). Label +the example history as follows: + +------------ + o---o---o---o---o master + \ + A---B---C---D---E subsystem + \ + X---Y---Z topic +------------ + +Now suppose the 'subsystem' maintainer decides to clean up his history +with an interactive rebase. He edits commits A and D (marked with a +`*`), decides to remove D entirely and moves B to the front. This +results in + +------------ + o---o---o---o---o master + | \ + | A*--C*--E'--B' subsystem + \ + A---B---C---D---E---X---Y---Z topic +------------ + +'git-rebase' can still tell that E'=E and B'=B, so a plain `git rebase +subsystem` would not duplicate those commits. However, it would +**resurrect** D (which may succeed silently!) and try to apply the +original versions of A and C (probably resulting in conflicts). + +To fix this, you have to manually transplant your own part of the +history to the new branch head. Looking at `git log`, you should be +able to determine that three commits on 'topic' are yours. Again +assuming you are already on 'topic', you can do +------------ + git rebase --onto subsystem HEAD~3 +------------ +to put things right. Of course, this again ripples onwards: +'everyone' downstream from 'subsystem' will have to 'manually' rebase +all their work! + + Authors ------ Written by Junio C Hamano <gitster@pobox.com> and -- 1.6.0.1.470.g200b ^ permalink raw reply related [flat|nested] 29+ messages in thread
* [PATCH 2/2] Documentation: Refer to git-rebase(1) to warn against rewriting 2008-09-11 15:38 ` [PATCH 1/2] " Thomas Rast @ 2008-09-11 15:38 ` Thomas Rast 2008-09-11 15:39 ` [RFC PATCH] Documentation: add manpage about workflows Thomas Rast 2008-09-12 1:15 ` [PATCH 1/2] Documentation: new upstream rebase recovery section in git-rebase Marcus Griep 2008-09-13 5:08 ` Junio C Hamano 2 siblings, 1 reply; 29+ messages in thread From: Thomas Rast @ 2008-09-11 15:38 UTC (permalink / raw) To: git; +Cc: Junio C Hamano This points readers at the "Recovering from upstream rebase" warning in git-rebase(1) when we talk about rewriting published history in the 'reset', 'commit --amend', and 'filter-branch' documentation. Signed-off-by: Thomas Rast <trast@student.ethz.ch> --- Documentation/git-commit.txt | 4 ++++ Documentation/git-filter-branch.txt | 4 +++- Documentation/git-reset.txt | 4 +++- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/Documentation/git-commit.txt b/Documentation/git-commit.txt index eb05b0f..eeba58d 100644 --- a/Documentation/git-commit.txt +++ b/Documentation/git-commit.txt @@ -144,6 +144,10 @@ It is a rough equivalent for: ------ but can be used to amend a merge commit. -- ++ +You should understand the implications of rewriting history if you +amend a commit that has already been published. (See the "RECOVERING +FROM UPSTREAM REBASE" section in linkgit:git-rebase[1].) -i:: --include:: diff --git a/Documentation/git-filter-branch.txt b/Documentation/git-filter-branch.txt index b0e710d..fed6de6 100644 --- a/Documentation/git-filter-branch.txt +++ b/Documentation/git-filter-branch.txt @@ -36,7 +36,9 @@ the objects and will not converge with the original branch. You will not be able to easily push and distribute the rewritten branch on top of the original branch. Please do not use this command if you do not know the full implications, and avoid using it anyway, if a simple single commit -would suffice to fix your problem. +would suffice to fix your problem. (See the "RECOVERING FROM UPSTREAM +REBASE" section in linkgit:git-rebase[1] for further information about +rewriting published history.) Always verify that the rewritten version is correct: The original refs, if different from the rewritten ones, will be stored in the namespace diff --git a/Documentation/git-reset.txt b/Documentation/git-reset.txt index 6abaeac..52aab5e 100644 --- a/Documentation/git-reset.txt +++ b/Documentation/git-reset.txt @@ -82,7 +82,9 @@ $ git reset --hard HEAD~3 <1> + <1> The last three commits (HEAD, HEAD^, and HEAD~2) were bad and you do not want to ever see them again. Do *not* do this if -you have already given these commits to somebody else. +you have already given these commits to somebody else. (See the +"RECOVERING FROM UPSTREAM REBASE" section in linkgit:git-rebase[1] for +the implications of doing so.) Undo a commit, making it a topic branch:: + -- 1.6.0.1.470.g200b ^ permalink raw reply related [flat|nested] 29+ messages in thread
* [RFC PATCH] Documentation: add manpage about workflows 2008-09-11 15:38 ` [PATCH 2/2] Documentation: Refer to git-rebase(1) to warn against rewriting Thomas Rast @ 2008-09-11 15:39 ` Thomas Rast 2008-09-11 16:37 ` Jakub Narebski ` (3 more replies) 0 siblings, 4 replies; 29+ messages in thread From: Thomas Rast @ 2008-09-11 15:39 UTC (permalink / raw) To: git; +Cc: Junio C Hamano This attempts to make a manpage about workflows that is both handy to point people at it and as a beginner's introduction. Signed-off-by: Thomas Rast <trast@student.ethz.ch> --- Documentation/Makefile | 2 +- Documentation/gitworkflows.txt | 326 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 327 insertions(+), 1 deletions(-) create mode 100644 Documentation/gitworkflows.txt diff --git a/Documentation/Makefile b/Documentation/Makefile index ded0e40..e33ddcb 100644 --- a/Documentation/Makefile +++ b/Documentation/Makefile @@ -6,7 +6,7 @@ MAN5_TXT=gitattributes.txt gitignore.txt gitmodules.txt githooks.txt \ gitrepository-layout.txt MAN7_TXT=gitcli.txt gittutorial.txt gittutorial-2.txt \ gitcvs-migration.txt gitcore-tutorial.txt gitglossary.txt \ - gitdiffcore.txt + gitdiffcore.txt gitworkflows.txt MAN_TXT = $(MAN1_TXT) $(MAN5_TXT) $(MAN7_TXT) MAN_XML=$(patsubst %.txt,%.xml,$(MAN_TXT)) diff --git a/Documentation/gitworkflows.txt b/Documentation/gitworkflows.txt new file mode 100644 index 0000000..3462000 --- /dev/null +++ b/Documentation/gitworkflows.txt @@ -0,0 +1,326 @@ +gitworkflows(7) +=============== + +NAME +---- +gitworkflows - An overview of recommended workflows with git + +SYNOPSIS +-------- +git * + + +DESCRIPTION +----------- + +This tutorial gives a brief overview of workflows recommended to +use, and collaborate with, Git. + +While the prose tries to motivate each of them, we formulate a set of +'rules' for quick reference. Do not always take them literally; you +should value good reasons higher than following a random manpage to +the letter. + + +SEPARATE CHANGES +---------------- + +As a general rule, you should try to split your changes into small +logical steps, and commit each of them. They should be consistent, +working independently of any later commits, pass the test suite, etc. + +To achieve this, try to commit your new work at least every couple +hours. You can always go back and edit the commits with `git rebase +--interactive` to further improve the history before you publish it. + + +MANAGING BRANCHES +----------------- + +In the following, we will assume there are 'developers', 'testers' and +'users'. Even if the "Testers" are actually an automated test suite +and all "Users" are developers themselves, try to think in these terms +as you follow a software change through its life cycle. + +Usually a change evolves in a few steps: + +* The developers implement a few iterations until it "seems to work". + +* The testers play with it, report bugs, test the fixes, eventually + clearing the change for stable releases. + +* As the users work with the new feature, they report bugs which will + have to be fixed. + +In the following sections we discuss some problems that arise from +such a "change flow", and how to solve them with Git. + +We consider a fictional project with (supported) stable branch +'maint', main testing/development branch 'master' and "bleeding edge" +branch 'next'. We collectively call these three branches 'main +branches'. + + +Merging upwards +~~~~~~~~~~~~~~~ + +Since Git is quite good at merges, one should try to use them to +propagate changes. For example, if a bug is fixed, you would want to +apply the corresponding fix to all main branches. + +A quick moment of thought reveals that you cannot do this by merging +"downwards" to older releases, since that would merge 'all' changes. +Hence the following: + +.Merge upwards +[caption="Rule: "] +===================================== +Always commit your fixes to the oldest supported branch that require +them. Then (periodically) merge the main branches upwards into each +other. +===================================== + +This gives a very controlled flow of fixes. If you notice that you +have applied a fix to e.g. 'master' that is also required in 'maint', +you will need to cherry-pick it (using linkgit:git-cherry-pick[1]) +downwards. This will happen a few times and is nothing to worry about +unless you do it all the time. + + +Topic branches +~~~~~~~~~~~~~~ + +Any nontrivial feature will require several patches to implement, and +may get extra bugfixes or improvements during its lifetime. If all +such commits were in one long linear history chain (e.g. if they were +all committed directly to, 'master'), it becomes very hard to see how +they belong together. + +The key concept here is "topic branches". The name is pretty self +explanatory, with a minor caveat that comes from the "merge upwards" +rule above: + +.Topic branches +[caption="Rule: "] +===================================== +Make a side branch for every topic. Fork it off at the oldest main +branch that you will eventually want to merge it into. +===================================== + +Many things can then be done very naturally: + +* To get the feature/bugfix into a main branch, simply merge it. If + the topic has evolved further in the meantime, merge again. + +* If you find you need new features from an 'other' branch to continue + working on your topic, merge 'other' to 'topic'. (However, do not + do this "just habitually", see below.) + +* If you find you forked off the wrong branch and want to move it + "back in time", use linkgit:git-rebase[1]. + +Note that the last two points clash: a topic that has been merged +elsewhere should not be rebased. See the section on RECOVERING FROM +UPSTREAM REBASE in linkgit:git-rebase[1]. + +We should point out that "habitually" (regularly for no real reason) +merging a main branch into your topics--and by extension, merging +anything upstream into anything downstream on a regular basis--is +frowned upon: + +.Merge to downstream only at well-defined points +[caption="Rule: "] +===================================== +Do not merge to downstream except: + +* with a good reason (such as upstream API changes that affect you), or + +* at well-defined points such as when an upstream release has been tagged. +===================================== + +Otherwise, the many resulting small merges will greatly clutter up +history. Anyone who later investigates the history of a file will +have to find out whether that merge affected the topic in +development. Linus hates it. An upstream might even inadvertently be +merged into a "more stable" branch. And so on. + + +Integration branches +~~~~~~~~~~~~~~~~~~~~ + +If you followed the last paragraph, you will now have many small topic +branches, and occasionally wonder how they interact. Perhaps the +result of merging them does not even work? But on the other hand, we +want to avoid merging them anywhere "stable" because such merges +cannot easily be undone. + +The solution, of course, is to make a merge that we can undo: merge +into a throw-away branch. + +.Integration branches +[caption="Rule: "] +===================================== +To test the interaction of several topics, merge them into a +throw-away branch. +===================================== + +If you make it (very) clear that this branch is going to be deleted +right after the testing, you can even publish this branch, for example +to give the testers a chance to work with it, or other developers a +chance to see if their in-progress work will be compatible. + + +SHARING WORK +------------ + +After the last section, you should know how to manage topics. In +general, you will not be the only person working on the project, so +you will have to share your work. + +Roughly speaking, there are two important workflows. Their +distinguishing mark is whether they can be used to propagate merges. +Medium to large projects will typically employ some mixture of the +two: + +* "Upstream" in the most general sense 'pushes' changes to the + repositor(ies) holding the main history. Everyone can 'pull' from + there to stay up to date. + +* Frequent contributors, subsystem maintainers, etc. may use push/pull + to send their changes upstream. + +* The rest -- typically anyone more than one or two levels away from the + main maintainer -- send patches by mail. + +None of these boundaries are sharp, so find out what works best for +you. + + +Push/pull +~~~~~~~~~ + +There are three main tools that can be used for this: + +* linkgit:git-push[1] copies your branches to a remote repository, + usually to one that can be read by all involved parties; + +* linkgit:git-fetch[1] that copies remote branches to your repository; + and + +* linkgit:git-pull[1] that is fetch and merge in one go. + +Note the last point. Do 'not' use 'git-pull' unless you actually want +to merge the remote branch. + +Getting changes out is easy: + +.Push/pull: Publishing branches/topics +[caption="Recipe: "] +===================================== +`git push <remote> <branch>` and tell everyone where they can fetch +from. +===================================== + +You will still have to tell people by other means, such as mail. (Git +provides the linkgit:request-pull[1] to send preformatted pull +requests to upstream maintainers to simplify this task.) + +If you just want to get the newest copies of the main branches, +staying up to date is easy too: + +.Push/pull: Staying up to date +[caption="Recipe: "] +===================================== +Use `git fetch <remote>` or `git remote update` to stay up to date. +===================================== + +Then simply fork your topic branches from the stable remotes as +explained earlier. + +If you are a maintainer and would like to merge other people's topic +branches to the main branches, they will typically send a request to +do so by mail. Such a request might say + +------------------------------------- +Please pull from + git://some.server.somewhere/random/repo.git mytopic +------------------------------------- + +In that case, 'git-pull' can do the fetch and merge in one go, as +follows. + +.Push/pull: Merging remote topics +[caption="Recipe: "] +===================================== +`git pull <url> <branch>` +===================================== + +Occasionally, the maintainer may get merge conflicts when he tries to +pull changes from downstream. In this case, he can ask downstream to +do the merge and resolve the conflicts themselves (perhaps they will +know better how to react). It is one of the rare cases where +downstream 'should' merge from upstream. + + +format-patch/am +~~~~~~~~~~~~~~~ + +If you are a contributor that sends changes upstream in the form of +emails, you should use topic branches as usual (see above). Then use +linkgit:git-format-patch[1] to generate the corresponding emails +(highly recommended over manually formatting them because it makes the +maintainer's life easier). + +.format-patch/am: Publishing branches/topics +[caption="Recipe: "] +===================================== +`git format-patch -M upstream..topic` and send out the resulting files. +===================================== + +See the linkgit:git-format-patch[1] manpage for further usage notes. +Also you should be aware that the maintainer may impose further +restrictions, such as "Signed-off-by" requirements. + +If the maintainer tells you that your patch no longer applies to the +current upstream, you will have to rebase your topic (you cannot use a +merge because you cannot format-patch merges): + +.format-patch/am: Keeping topics up to date +[caption="Recipe: "] +===================================== +`git rebase upstream` +===================================== + +You can then fix the conflicts during the rebase. Presumably you have +not published your topic other than by mail, so rebasing it is not a +problem. + +If you receive such a patch (as maintainer, or perhaps reader of the +mailing list it was sent to), save the mail to a file and use +'git-am': + +.format-patch/am: Publishing branches/topics +[caption="Recipe: "] +===================================== +`git am < patch` +===================================== + +One feature worth pointing out is the three-way merge, which can help +if you get conflicts because of renames: `git am -3` will use index +information contained in patches to reconstruct a merge base. See +linkgit:git-am[1] for other options. + + +SEE ALSO +-------- +linkgit:gittutorial[7], +linkgit:git-push[1], +linkgit:git-pull[1], +linkgit:git-merge[1], +linkgit:git-rebase[1], +linkgit:git-format-patch[1], +linkgit:git-am[1] + +GIT +--- +Part of the linkgit:git[1] suite. -- 1.6.0.1.470.g200b ^ permalink raw reply related [flat|nested] 29+ messages in thread
* Re: [RFC PATCH] Documentation: add manpage about workflows 2008-09-11 15:39 ` [RFC PATCH] Documentation: add manpage about workflows Thomas Rast @ 2008-09-11 16:37 ` Jakub Narebski 2008-09-12 7:26 ` [RFH] Asciidoc non-example blocks [was: Re: [RFC PATCH] Documentation: add manpage about workflows] Thomas Rast ` (2 subsequent siblings) 3 siblings, 0 replies; 29+ messages in thread From: Jakub Narebski @ 2008-09-11 16:37 UTC (permalink / raw) To: git Thomas Rast wrote: > This attempts to make a manpage about workflows that is both handy to > point people at it and as a beginner's introduction. [...] Very nice. -- Jakub Narebski Warsaw, Poland ShadeHawk on #git ^ permalink raw reply [flat|nested] 29+ messages in thread
* [RFH] Asciidoc non-example blocks [was: Re: [RFC PATCH] Documentation: add manpage about workflows] 2008-09-11 15:39 ` [RFC PATCH] Documentation: add manpage about workflows Thomas Rast 2008-09-11 16:37 ` Jakub Narebski @ 2008-09-12 7:26 ` Thomas Rast 2008-09-20 0:22 ` [RFC PATCH] Documentation: add manpage about workflows Santi Béjar 2008-09-21 20:26 ` Dmitry Potapov 3 siblings, 0 replies; 29+ messages in thread From: Thomas Rast @ 2008-09-12 7:26 UTC (permalink / raw) To: git [-- Attachment #1: Type: text/plain, Size: 585 bytes --] Thomas Rast wrote: > +.Merge upwards > +[caption="Rule: "] > +===================================== > +Always commit your fixes to the oldest supported branch that require > +them. Then (periodically) merge the main branches upwards into each > +other. > +===================================== Turns out that asciidoc, at least the 8.2.5 on my system, does not honour the custom caption when converting to manpages. They become numbered 'Example' blocks instead. Is there another way to get a similar result? - Thomas -- Thomas Rast trast@student.ethz.ch [-- Attachment #2: This is a digitally signed message part. --] [-- Type: application/pgp-signature, Size: 197 bytes --] ^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [RFC PATCH] Documentation: add manpage about workflows 2008-09-11 15:39 ` [RFC PATCH] Documentation: add manpage about workflows Thomas Rast 2008-09-11 16:37 ` Jakub Narebski 2008-09-12 7:26 ` [RFH] Asciidoc non-example blocks [was: Re: [RFC PATCH] Documentation: add manpage about workflows] Thomas Rast @ 2008-09-20 0:22 ` Santi Béjar 2008-09-21 20:26 ` Dmitry Potapov 3 siblings, 0 replies; 29+ messages in thread From: Santi Béjar @ 2008-09-20 0:22 UTC (permalink / raw) To: Thomas Rast; +Cc: git, Junio C Hamano On Thu, Sep 11, 2008 at 5:39 PM, Thomas Rast <trast@student.ethz.ch> wrote: > This attempts to make a manpage about workflows that is both handy to > point people at it and as a beginner's introduction. > > Signed-off-by: Thomas Rast <trast@student.ethz.ch> > --- > Documentation/Makefile | 2 +- > Documentation/gitworkflows.txt | 326 + +++++++++++++++++++++++++++++++++++++++ It should be linked/advertised from other pages (git, tutorial, everyday?) > diff --git a/Documentation/gitworkflows.txt b/Documentation/gitworkflows.txt > new file mode 100644 > index 0000000..3462000 > --- /dev/null > +++ b/Documentation/gitworkflows.txt [...] > +To achieve this, try to commit your new work at least every couple > +hours. You can always go back and edit the commits with `git rebase > +--interactive` to further improve the history before you publish it. I do not agree with this. I don´t much differences between a big patch and the same patch divided randomly. To achieve this, try to commit when you are minimally satisfied with the new code or before large changes. You can always go back and edit the commits with `git rebase --interactive` to further improve the history before you publish it, or you could split a big patch as is explained in gitlink:git-stash. > + > + > +MANAGING BRANCHES > +----------------- > + > +In the following, we will assume there are 'developers', 'testers' and > +'users'. Even if the "Testers" are actually an automated test suite > +and all "Users" are developers themselves, try to think in these terms "Testers" -> 'testers', ... > +as you follow a software change through its life cycle. > + > +Usually a change evolves in a few steps: > + > +* The developers implement a few iterations until it "seems to work". > + > +* The testers play with it, report bugs, test the fixes, eventually > + clearing the change for stable releases. > + > +* As the users work with the new feature, they report bugs which will > + have to be fixed. > + > +In the following sections we discuss some problems that arise from > +such a "change flow", and how to solve them with Git. > + > +We consider a fictional project with (supported) stable branch > +'maint', main testing/development branch 'master' and "bleeding edge" > +branch 'next'. We collectively call these three branches 'main > +branches'. You mention the next branch but it is not explained. > + > + > +Merging upwards > +~~~~~~~~~~~~~~~ > + > +Since Git is quite good at merges, one should try to use them to > +propagate changes. For example, if a bug is fixed, you would want to > +apply the corresponding fix to all main branches. > + > +A quick moment of thought reveals that you cannot do this by merging > +"downwards" to older releases, since that would merge 'all' changes. all development changes > +Hence the following: > + > +.Merge upwards > +[caption="Rule: "] > +===================================== > +Always commit your fixes to the oldest supported branch that require > +them. Then (periodically) merge the main branches upwards into each > +other. > +===================================== > + > +This gives a very controlled flow of fixes. If you notice that you > +have applied a fix to e.g. 'master' that is also required in 'maint', > +you will need to cherry-pick it (using linkgit:git-cherry-pick[1]) > +downwards. This will happen a few times and is nothing to worry about > +unless you do it all the time. > + > + > +Topic branches > +~~~~~~~~~~~~~~ > + > +Any nontrivial feature will require several patches to implement, and > +may get extra bugfixes or improvements during its lifetime. If all > +such commits were in one long linear history chain (e.g. if they were > +all committed directly to, 'master'), it becomes very hard to see how > +they belong together. > + > +The key concept here is "topic branches". The name is pretty self > +explanatory, with a minor caveat that comes from the "merge upwards" > +rule above: > + > +.Topic branches > +[caption="Rule: "] > +===================================== > +Make a side branch for every topic. Fork it off at the oldest main > +branch that you will eventually want to merge it into. > +===================================== > + > +Many things can then be done very naturally: > + > +* To get the feature/bugfix into a main branch, simply merge it. If > + the topic has evolved further in the meantime, merge again. > + > +* If you find you need new features from an 'other' branch to continue ... from the branch 'other' to continue > + working on your topic, merge 'other' to 'topic'. (However, do not > + do this "just habitually", see below.) > + > +* If you find you forked off the wrong branch and want to move it > + "back in time", use linkgit:git-rebase[1]. > + > +Note that the last two points clash: a topic that has been merged > +elsewhere should not be rebased. See the section on RECOVERING FROM > +UPSTREAM REBASE in linkgit:git-rebase[1]. > + > +We should point out that "habitually" (regularly for no real reason) > +merging a main branch into your topics--and by extension, merging > +anything upstream into anything downstream on a regular basis--is > +frowned upon: > + > +.Merge to downstream only at well-defined points > +[caption="Rule: "] > +===================================== > +Do not merge to downstream except: > + > +* with a good reason (such as upstream API changes that affect you), or > + > +* at well-defined points such as when an upstream release has been tagged. Do not merge to downstream except with a good reasons: * API changes that affect you branch * your branch no longer merges cleanly * when your branch is way not up-to-date. And mainly at well-defined points, such as when an upstream release has been tagged, preferably stable release. > +===================================== > + > +Otherwise, the many resulting small merges will greatly clutter up > +history. Anyone who later investigates the history of a file will > +have to find out whether that merge affected the topic in > +development. Linus hates it. An upstream might even inadvertently be > +merged into a "more stable" branch. And so on. Yes, the main point is that Linus hates it :-) > + > + > +Integration branches > +~~~~~~~~~~~~~~~~~~~~ > + > +If you followed the last paragraph, you will now have many small topic > +branches, and occasionally wonder how they interact. Perhaps the > +result of merging them does not even work? But on the other hand, we > +want to avoid merging them anywhere "stable" because such merges > +cannot easily be undone. > + > +The solution, of course, is to make a merge that we can undo: merge > +into a throw-away branch. > + > +.Integration branches > +[caption="Rule: "] > +===================================== > +To test the interaction of several topics, merge them into a > +throw-away branch. > +===================================== > + > +If you make it (very) clear that this branch is going to be deleted > +right after the testing, you can even publish this branch, for example > +to give the testers a chance to work with it, or other developers a > +chance to see if their in-progress work will be compatible. > + > + > +SHARING WORK > +------------ > + > +After the last section, you should know how to manage topics. In > +general, you will not be the only person working on the project, so > +you will have to share your work. > + > +Roughly speaking, there are two important workflows. Their > +distinguishing mark is whether they can be used to propagate merges. and one keeps the branch history while the other rewrite it. > +Medium to large projects will typically employ some mixture of the > +two: I would remove this. The different actors share their work as: > + > +* "Upstream" in the most general sense 'pushes' changes to the > + repositor(ies) holding the main history. Everyone can 'pull' from > + there to stay up to date. s/repositor(ies)/repository/ And: She pull from her (trusted) downstreams, and applies the patches from the others. > + > +* Frequent contributors, subsystem maintainers, etc. may use push/pull > + to send their changes upstream. ? Maybe: * (Trusted) Downstreams act like the Upstreams but publish their changes in their own repository. > + > +* The rest -- typically anyone more than one or two levels away from the > + main maintainer -- send patches by mail. > + > +None of these boundaries are sharp, so find out what works best for > +you. > + > + > +Push/pull > +~~~~~~~~~ > + > +There are three main tools that can be used for this: > + > +* linkgit:git-push[1] copies your branches to a remote repository, > + usually to one that can be read by all involved parties; > + > +* linkgit:git-fetch[1] that copies remote branches to your repository; > + and > + > +* linkgit:git-pull[1] that is fetch and merge in one go. > + > +Note the last point. Do 'not' use 'git-pull' unless you actually want > +to merge the remote branch. No need to repeat what is explained in the tutorial. > + > +Getting changes out is easy: > + > +.Push/pull: Publishing branches/topics > +[caption="Recipe: "] > +===================================== > +`git push <remote> <branch>` and tell everyone where they can fetch > +from. > +===================================== > + > +You will still have to tell people by other means, such as mail. (Git s/tell/inform/ > +provides the linkgit:request-pull[1] to send preformatted pull > +requests to upstream maintainers to simplify this task.) > + > +If you just want to get the newest copies of the main branches, > +staying up to date is easy too: > + > +.Push/pull: Staying up to date > +[caption="Recipe: "] > +===================================== > +Use `git fetch <remote>` or `git remote update` to stay up to date. > +===================================== > + > +Then simply fork your topic branches from the stable remotes as > +explained earlier. > + In tutorial.txt. And it applies to everybody (upstream, contributors,...) > +If you are a maintainer and would like to merge other people's topic > +branches to the main branches, they will typically send a request to > +do so by mail. Such a request might say > + > +------------------------------------- > +Please pull from > + git://some.server.somewhere/random/repo.git mytopic > +------------------------------------- > + > +In that case, 'git-pull' can do the fetch and merge in one go, as > +follows. > + > +.Push/pull: Merging remote topics > +[caption="Recipe: "] > +===================================== > +`git pull <url> <branch>` > +===================================== > + In tutorial. I think they are well explained in the tutorial. No need to repeat it here. You could just mentions the tools and the recipies. > +Occasionally, the maintainer may get merge conflicts when he tries to > +pull changes from downstream. In this case, he can ask downstream to > +do the merge and resolve the conflicts themselves (perhaps they will > +know better how to react). It is one of the rare cases where > +downstream 'should' merge from upstream. > + > + > +format-patch/am > +~~~~~~~~~~~~~~~ > + > +If you are a contributor that sends changes upstream in the form of > +emails, you should use topic branches as usual (see above). Then use > +linkgit:git-format-patch[1] to generate the corresponding emails > +(highly recommended over manually formatting them because it makes the > +maintainer's life easier). > + > +.format-patch/am: Publishing branches/topics > +[caption="Recipe: "] > +===================================== > +`git format-patch -M upstream..topic` and send out the resulting files. > +===================================== > + > +See the linkgit:git-format-patch[1] manpage for further usage notes. > +Also you should be aware that the maintainer may impose further > +restrictions, such as "Signed-off-by" requirements. the further restrictions are not only for git-format-patch users. > + > +If the maintainer tells you that your patch no longer applies to the > +current upstream, you will have to rebase your topic (you cannot use a > +merge because you cannot format-patch merges): > + > +.format-patch/am: Keeping topics up to date > +[caption="Recipe: "] > +===================================== > +`git rebase upstream` > +===================================== git rebase <upstream> > + > +You can then fix the conflicts during the rebase. Presumably you have > +not published your topic other than by mail, so rebasing it is not a > +problem. > + > +If you receive such a patch (as maintainer, or perhaps reader of the as a reader > +mailing list it was sent to), save the mail to a file and use > +'git-am': > + > +.format-patch/am: Publishing branches/topics > +[caption="Recipe: "] > +===================================== > +`git am < patch` > +===================================== > + > +One feature worth pointing out is the three-way merge, which can help > +if you get conflicts because of renames: `git am -3` will use index > +information contained in patches to reconstruct a merge base. See > +linkgit:git-am[1] for other options. > + > + > +SEE ALSO > +-------- > +linkgit:gittutorial[7], > +linkgit:git-push[1], > +linkgit:git-pull[1], > +linkgit:git-merge[1], > +linkgit:git-rebase[1], > +linkgit:git-format-patch[1], > +linkgit:git-am[1] > + > +GIT > +--- > +Part of the linkgit:git[1] suite. > -- Santi- ^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [RFC PATCH] Documentation: add manpage about workflows 2008-09-11 15:39 ` [RFC PATCH] Documentation: add manpage about workflows Thomas Rast ` (2 preceding siblings ...) 2008-09-20 0:22 ` [RFC PATCH] Documentation: add manpage about workflows Santi Béjar @ 2008-09-21 20:26 ` Dmitry Potapov 2008-09-30 16:05 ` Thomas Rast 3 siblings, 1 reply; 29+ messages in thread From: Dmitry Potapov @ 2008-09-21 20:26 UTC (permalink / raw) To: Thomas Rast; +Cc: git, Junio C Hamano On Thu, Sep 11, 2008 at 05:39:45PM +0200, Thomas Rast wrote: > This attempts to make a manpage about workflows that is both handy to > point people at it and as a beginner's introduction. Thank you for your attempt. It is clearly a missing part of the Git documentation. I have a few comments to it below. > +SEPARATE CHANGES > +---------------- > + > +As a general rule, you should try to split your changes into small > +logical steps, and commit each of them. They should be consistent, > +working independently of any later commits, pass the test suite, etc. I would rather add some explanation why it is a good idea. Something like this: "This makes the review process much easier, as well as, makes git bisect much more useful in finding the cause of regressions." > + > +To achieve this, try to commit your new work at least every couple > +hours. You can always go back and edit the commits with `git rebase > +--interactive` to further improve the history before you publish it. I like the idea of this paragraph but not its wording. Maybe this will be better (just a variant): "To achieve this, try to split your work in small steps from the very beginning. It is always easier to squash a few commits together than splitting one big commit into a few. Don't be afraid making steps too small or that they are not perfect yet. You can always go back later and edit the commits with `git rebase --interactive` before you publish it." > + > +MANAGING BRANCHES > +----------------- > + > +In the following, we will assume there are 'developers', 'testers' and > +'users'. Even if the "Testers" are actually an automated test suite > +and all "Users" are developers themselves, try to think in these terms > +as you follow a software change through its life cycle. > + > +Usually a change evolves in a few steps: > + > +* The developers implement a few iterations until it "seems to work". > + > +* The testers play with it, report bugs, test the fixes, eventually > + clearing the change for stable releases. Perhaps, the above two points are the most controversial in my opinion. First, I would expect developers to implement a few iterations until it (their work) passes the automated test suite and peer review. Only then their work is merged into 'next' (or into a similar branch, which constitute that this series is published now). Second, I am not sure what you meant by testers clears changes for stable releases, especially after you stated "Testers" may be an automated test suite. Whether some change is included is always a conscious decision of the project maintainer. The fact that some change has passed all tests successfully only clears it for including into 'next'. > + > +* As the users work with the new feature, they report bugs which will > + have to be fixed. > + > +In the following sections we discuss some problems that arise from > +such a "change flow", and how to solve them with Git. > + > +We consider a fictional project with (supported) stable branch > +'maint', main testing/development branch 'master' and "bleeding edge" > +branch 'next'. We collectively call these three branches 'main > +branches'. The idea of 'next' is not obvious from your above explanation. When I started to learn how Git workflow works, I read something like above and was very puzzled what is the purpose of having two development branches: 'master' and 'next'. Only later I realized that it is necessary to give flexibility in making decisions of what should be included in the next stable release and what may need more "cooking" to prove their reliability and usefulness. > + > + > +Merging upwards > +~~~~~~~~~~~~~~~ > + > +Since Git is quite good at merges, one should try to use them to > +propagate changes. For example, if a bug is fixed, you would want to > +apply the corresponding fix to all main branches. The first and second sentences are a bit disconnected here. I would rather write the second one like this: "An example of such a change can be a bug fix, which should be applied to all main branches." Another thing is that I am not sure that the provided reason for doing so ("Git is quite good at merges") is good enough. It can be said that Git is quite good at cherry-picking too. Yet, we use merge, because it allows to deal with large number of patches easier. Merge can be easily visualized and understood as every merge point means that all changes before it are included. However, to being able use merge, the developer has to start from the oldest branch that will include this change. This is a clear restriction over the anarchic nature of cherry-picking (where you can introduce a change to an arbitrary branch and then cherry-pick to others), but it pays off in the long run by better maintainability of the project. Thus the recommended practice is a strong preference to use merge over cherry-picking. It does not mean that cherry-picking should be completely excluded. Occasionally, it may be useful. > + > +A quick moment of thought reveals that you cannot do this by merging > +"downwards" to older releases, since that would merge 'all' changes. IMHO, expressions such as "a quick moment of thought reveals..." is more suitable for blogs than for serious documentation. > +Hence the following: > + > +.Merge upwards > +[caption="Rule: "] > +===================================== > +Always commit your fixes to the oldest supported branch that require > +them. Then (periodically) merge the main branches upwards into each > +other. > +===================================== Perhaps, it is worth to note here that a non-trivial fixes can be implemented as topic branches, which starts from the oldest branch that needs them. > + > +This gives a very controlled flow of fixes. If you notice that you > +have applied a fix to e.g. 'master' that is also required in 'maint', > +you will need to cherry-pick it (using linkgit:git-cherry-pick[1]) > +downwards. This will happen a few times and is nothing to worry about > +unless you do it all the time. > + > + > +Topic branches > +~~~~~~~~~~~~~~ > + > +Any nontrivial feature will require several patches to implement, and > +may get extra bugfixes or improvements during its lifetime. If all > +such commits were in one long linear history chain (e.g. if they were > +all committed directly to, 'master'), it becomes very hard to see how > +they belong together. There is a far more important reason to use topic branches than ecstatic pleasure from being able to see related changes grouped together in the history. The main reason to use topic branches is to facilitate parallel development. Though the idea that anyone commit to the main development branch ('master') is very appealing due to its simplicity, it leads to problems down the road. Namely, not all good sounding ideas turns out good in reality. In the workflow where everyone commits to 'master' there are only two ways to deal with that. The first approach is not let developers to commit their changes until they have completely finished their work and passed all tests and code-review, and their work deemed important enough to be included in the next feature release. The second approach is to commit their work in progress in the hope that it will succeed, and if not then to rollback changes. Neither of these two approaches is satisfactory, especially for large projects. The first approach means that developers are under a great stress due to inability to save their work in progress, they accumulate a huge patch, which is very difficult to review, often include some other changes unrelated to the stated goal, and makes the history of the project nearly useless for bisecting (linkgit:git-bisect[1]) when it comes to finding a regression. The second approach means that the project history gets contaminating with a great number of changes that eventually didn't work out. Moreover, reverting changes that are belong to some failed work may extremely difficult as other changes intervene with them. So, this reverting is hardly ever done completely in practice if it is done at all, which leads to a lot of garbage in the source code. Obviously, the history of this project is completely useless for bisecting as many commits do not really work if they are compiled at all. Also, this approach leads to an extremely long stabilization period as it is determined by the time when slowest going work will be in good shape for release. Using topic branches immune to that problem as feature are included into 'master' when they are ready. Moreover, feature branches unless they are "publish" can go through cycles of testing, review, and interactive rebasing to edit and improve individual commits. Thus the finally published history is clean and easy to bisect. > + > +Roughly speaking, there are two important workflows. I think it would make sense to name them here. > Their > +distinguishing mark is whether they can be used to propagate merges. Perhaps, it would be better to say: "They are distinguished by the ability to propagate merges." However, this is not the only distinguish between them. Besides, I am not sure how this one is connected with the rest of the paragraph: > +Medium to large projects will typically employ some mixture of the > +two: > + > +* "Upstream" in the most general sense 'pushes' changes to the > + repositor(ies) holding the main history. IMHO, it would be better: s/the main history/the official history of the project/ > Everyone can 'pull' from there to stay up to date. Would that entrench the wrong idea that one needs to do 'pull' habitually? And the habitual 'pull' results in habitual 'merge'. > + > +* Frequent contributors, subsystem maintainers, etc. may use push/pull > + to send their changes upstream. This is nitpicking, but you cannot use 'pull' to send changes. However, I suppose you meant to make your repository available for other people to pull from it. > + > +* The rest -- typically anyone more than one or two levels away from the > + main maintainer -- send patches by mail. After reading "mixture of the two:" above, I expected these two being named, but instead I can see three points. So, it is confusing. > +If the maintainer tells you that your patch no longer applies to the > +current upstream, you will have to rebase your topic (you cannot use a > +merge because you cannot format-patch merges): > + > +.format-patch/am: Keeping topics up to date > +[caption="Recipe: "] > +===================================== > +`git rebase upstream` > +===================================== Maybe, git pull --rebase is better advice here as it will also fetch the latest changes from the upstream. > + > +You can then fix the conflicts during the rebase. Presumably you have > +not published your topic other than by mail, so rebasing it is not a > +problem. > + > +If you receive such a patch (as maintainer, or perhaps reader of the > +mailing list it was sent to), save the mail to a file and use > +'git-am': > + > +.format-patch/am: Publishing branches/topics > +[caption="Recipe: "] > +===================================== > +`git am < patch` > +===================================== > + > +One feature worth pointing out is the three-way merge, which can help > +if you get conflicts because of renames: Could it not be any other reason besides renames? Maybe it is better to drop "because of renames" here. > `git am -3` will use index > +information contained in patches Because the word "index" is often used in Git in the different meaning (a.k.a cache), I would re-write this sentence to avoid confusion as: "`git am -3` will use information contained in index lines of patches" > to reconstruct a merge base. See If I did not know how git am -3 works, reading this would make me think that git am somehow manage to figure out a common ancestor (commit), while it uses index lines of the patch to learn the identity of the blob that was used as the starting point to create the patch, and if this blob is available locally, git am -3 performs 3-way merge. So, "reconstruct a merge base" is hardly appropriate here. Dmitry ^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [RFC PATCH] Documentation: add manpage about workflows 2008-09-21 20:26 ` Dmitry Potapov @ 2008-09-30 16:05 ` Thomas Rast 2008-09-30 16:07 ` Thomas Rast 2008-10-01 9:54 ` Santi Béjar 0 siblings, 2 replies; 29+ messages in thread From: Thomas Rast @ 2008-09-30 16:05 UTC (permalink / raw) To: Dmitry Potapov; +Cc: git, Santi Béjar, Junio C Hamano [-- Attachment #1: Type: text/plain, Size: 12980 bytes --] As a quick status update, mostly to show that I haven't forgotten about this topic: Thanks Santi and Dmitry for your comments. You have raised some very good points, and I attempted to fix these issues. Unfortunately, in some places I got stuck trying to work out good explanations for the workings of git.git, and some of the newer rearrangements left the lead of "Merging branches" in a dire state. I'll see if I can find a good solution myself, but suggestions would be welcome in any case. The WIP text is below, and I'll follow up with an interdiff to the last version. - Thomas --- 8< --- gitworkflows(7) =============== NAME ---- gitworkflows - An overview of recommended workflows with git SYNOPSIS -------- git * DESCRIPTION ----------- This document attempts to write down and motivate some of the workflow elements used for `git.git` itself. Many ideas apply in general, though the full workflow is rarely required for smaller projects with fewer people involved. We formulate a set of 'rules' for quick reference, while the prose tries to motivate each of them. Do not always take them literally; you should value good reasons for your actions higher than manpages such as this one. SEPARATE CHANGES ---------------- As a general rule, you should try to split your changes into small logical steps, and commit each of them. They should be consistent, working independently of any later commits, pass the test suite, etc. This makes the review process much easier, and the history much more useful for later inspection and analysis, for example with linkgit:git-blame[1] and linkgit:git-bisect[1]. To achieve this, try to split your work into small steps from the very beginning. It is always easier to squash a few commits together than to split one big commit into several. Don't be afraid of making too small or imperfect steps along the way. You can always go back later and edit the commits with `git rebase \--interactive` before you publish them. MANAGING BRANCHES ----------------- Usually a feature (or other change) evolves in stages: it "graduates" from patch to the testing branches and on to stable releases. During this process, it may require fixes or improvements. XXX terrible paragraph XXX Merges (as opposed to cherry-picks, see below) greatly simplify handling large numbers of commits, so a scalable workflow needs to use merges. Fortunately Git is very good at merging. XXX non sequitur XXX In the following sections we discuss some problems that arise from such a "change flow", and how to solve them with Git. Graduation ~~~~~~~~~~ As a given feature goes from experimental to stable, it also "graduates" between the corresponding branches of the software. `git.git` uses the following 'main branches': * 'master' tracks the commits that should go into the next release; * 'maint' tracks the commits that should go into the next "maintenance release", i.e., update of the last released stable version; and * 'next' is intended as a testing branch for people who like to use more experimental stuff. There is a fourth official branch that is used slightly differently: * 'pu' (proposed updates) is an integration branch for things that are not quite ready for inclusion yet (see "Integration Branches" below). Conceptually, the feature enters at an unstable branch (usually 'next' or 'pu'), and "graduates" to 'master' for the next release once it is considered stable enough. Merging upwards ~~~~~~~~~~~~~~~ As explained above, features conceptually "graduate downwards" to older releases. This cannot be done by actually merging downwards, however, since that would merge 'all' changes on the unstable branch into the stable one. Hence the following: .Merge upwards [caption="Rule: "] ===================================== Always commit your fixes to the oldest supported branch that require them. Then (periodically) merge the main branches upwards into each other. ===================================== This gives a very controlled flow of fixes. If you notice that you have applied a fix to e.g. 'master' that is also required in 'maint', you will need to cherry-pick it (using linkgit:git-cherry-pick[1]) downwards. This will happen a few times and is nothing to worry about unless you do it very frequently. Topic branches ~~~~~~~~~~~~~~ Any nontrivial feature will require several patches to implement, and may get extra bugfixes or improvements during its lifetime. Committing everything directly on the main branches leads to many problems: Bad commits cannot be undone, so they must be reverted one by one, which creates confusing histories and further error potential when you forget to revert part of a group of changes. Working in parallel mixes up the changes, creating further confusion. The key concept here is "topic branches". The name is pretty self explanatory, with a caveat that comes from the "merge upwards" rule above: .Topic branches [caption="Rule: "] ===================================== Make a side branch for every topic (feature, bugfix, ...). Fork it off at the oldest main branch that you will eventually want to merge it into. ===================================== Many things can then be done very naturally: * To get the feature/bugfix into a main branch, simply merge it. If the topic has evolved further in the meantime, merge again. * If you find you need new features from the branch 'other' to continue working on your topic, merge 'other' to 'topic'. (However, do not do this "just habitually", see below.) * If you find you forked off the wrong branch and want to move it "back in time", use linkgit:git-rebase[1]. Note that the last two points clash: a topic that has been merged elsewhere should not be rebased. See the section on RECOVERING FROM UPSTREAM REBASE in linkgit:git-rebase[1]. We should point out that "habitually" (regularly for no real reason) merging a main branch into your topics -- and by extension, merging anything upstream into anything downstream on a regular basis -- is frowned upon: .Merge to downstream only at well-defined points [caption="Rule: "] ===================================== Do not merge to downstream except: * with a good reason: upstream API changes affect your branch; your branch no longer merges to upstream cleanly; etc. * at well-defined points such as when an upstream release has been tagged. ===================================== Otherwise, the many resulting small merges will greatly clutter up history. Anyone who later investigates the history of a file will have to find out whether that merge affected the topic in development. An upstream might even inadvertently be merged into a "more stable" branch. And so on. Integration branches ~~~~~~~~~~~~~~~~~~~~ If you followed the last paragraph, you will now have many small topic branches, and occasionally wonder how they interact. Perhaps the result of merging them does not even work? But on the other hand, we want to avoid merging them anywhere "stable" because such merges cannot easily be undone. The solution, of course, is to make a merge that we can undo: merge into a throw-away branch. .Integration branches [caption="Rule: "] ===================================== To test the interaction of several topics, merge them into a throw-away branch. ===================================== If you make it (very) clear that this branch is going to be deleted right after the testing, you can even publish this branch, for example to give the testers a chance to work with it, or other developers a chance to see if their in-progress work will be compatible. `git.git` has such an official integration branch called 'pu'. You must never base any work on such a throw-away branch! SHARING WORK ------------ After the last section, you should know how to manage topics. In general, you will not be the only person working on the project, so you will have to share your work. Roughly speaking, there are two important workflows: push/pull and format-patch/am. The important difference is that push/pull can propagate merges, while format-patch cannot. Medium to large projects will typically employ some mixture of the two: * "Upstream" in the most general sense 'pushes' changes to the repositor(ies) holding the official history of the project. Everyone can 'fetch' from there to stay up to date. * Frequent contributors, subsystem maintainers, etc. may push to a public repository to make their changes available to upstream. * The rest -- typically anyone more than one or two levels away from the main maintainer -- send patches by mail. None of these boundaries are sharp, so find out what works best for you. Push/pull ~~~~~~~~~ There are three main tools that can be used for this: * linkgit:git-push[1] copies your branches to a remote repository, usually to one that can be read by all involved parties; * linkgit:git-fetch[1] that copies remote branches to your repository; and * linkgit:git-pull[1] that does fetch and merge in one go. Note the last point. Do 'not' use 'git-pull' unless you actually want to merge the remote branch. Getting changes out is easy: .Push/pull: Publishing branches/topics [caption="Recipe: "] ===================================== `git push <remote> <branch>` and tell everyone where they can fetch from. ===================================== You will still have to tell people by other means, such as mail. (Git provides the linkgit:request-pull[1] to send preformatted pull requests to upstream maintainers to simplify this task.) If you just want to get the newest copies of the main branches, staying up to date is easy too: .Push/pull: Staying up to date [caption="Recipe: "] ===================================== Use `git fetch <remote>` or `git remote update` to stay up to date. ===================================== Then simply fork your topic branches from the stable remotes as explained earlier. If you are a maintainer and would like to merge other people's topic branches to the main branches, they will typically send a request to do so by mail. Such a request might say ------------------------------------- Please pull from git://some.server.somewhere/random/repo.git mytopic ------------------------------------- In that case, 'git-pull' can do the fetch and merge in one go, as follows. .Push/pull: Merging remote topics [caption="Recipe: "] ===================================== `git pull <url> <branch>` ===================================== Occasionally, the maintainer may get merge conflicts when he tries to pull changes from downstream. In this case, he can ask downstream to do the merge and resolve the conflicts themselves (perhaps they will know better how to resolve them). It is one of the rare cases where downstream 'should' merge from upstream. format-patch/am ~~~~~~~~~~~~~~~ If you are a contributor that sends changes upstream in the form of emails, you should use topic branches as usual (see above). Then use linkgit:git-format-patch[1] to generate the corresponding emails (highly recommended over manually formatting them because it makes the maintainer's life easier). .format-patch/am: Publishing branches/topics [caption="Recipe: "] ===================================== * `git format-patch -M upstream..topic` to turn them into preformatted patch files * `git send-email --to=<recipient> <patches>` ===================================== See the linkgit:git-format-patch[1] and linkgit:git-send-email[1] manpages for further usage notes. Also you should be aware that the maintainer may impose further restrictions, such as "Signed-off-by" requirements. If the maintainer tells you that your patch no longer applies to the current upstream, you will have to rebase your topic (you cannot use a merge because you cannot format-patch merges): .format-patch/am: Keeping topics up to date [caption="Recipe: "] ===================================== `git pull --rebase <url> <branch>` ===================================== You can then fix the conflicts during the rebase. Presumably you have not published your topic other than by mail, so rebasing it is not a problem. If you receive such a patch (as maintainer, or perhaps as a reader of the mailing list it was sent to), save the mail to a file and use 'git-am': .format-patch/am: Publishing branches/topics [caption="Recipe: "] ===================================== `git am < patch` ===================================== One feature worth pointing out is the three-way merge, which can help if you get conflicts: `git am -3` will use index information contained in patches to figure out the merge base. See linkgit:git-am[1] for other options. SEE ALSO -------- linkgit:gittutorial[7], linkgit:git-push[1], linkgit:git-pull[1], linkgit:git-merge[1], linkgit:git-rebase[1], linkgit:git-format-patch[1], linkgit:git-send-email[1], linkgit:git-am[1] GIT --- Part of the linkgit:git[1] suite. [-- Attachment #2: This is a digitally signed message part. --] [-- Type: application/pgp-signature, Size: 197 bytes --] ^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [RFC PATCH] Documentation: add manpage about workflows 2008-09-30 16:05 ` Thomas Rast @ 2008-09-30 16:07 ` Thomas Rast 2008-10-01 9:54 ` Santi Béjar 1 sibling, 0 replies; 29+ messages in thread From: Thomas Rast @ 2008-09-30 16:07 UTC (permalink / raw) To: Dmitry Potapov; +Cc: git, Santi Béjar, Junio C Hamano I wrote: > The WIP text is below, and I'll follow up with an interdiff to the > last version. diff --git a/Documentation/gitworkflows.txt b/Documentation/gitworkflows.txt index b4b43da..87c2270 100644 --- a/Documentation/gitworkflows.txt +++ b/Documentation/gitworkflows.txt @@ -13,13 +13,15 @@ git * DESCRIPTION ----------- -This tutorial gives a brief overview of workflows recommended to -use, and collaborate with, Git. +This document attempts to write down and motivate some of the workflow +elements used for `git.git` itself. Many ideas apply in general, +though the full workflow is rarely required for smaller projects with +fewer people involved. -While the prose tries to motivate each of them, we formulate a set of -'rules' for quick reference. Do not always take them literally; you -should value good reasons higher than following a random manpage to -the letter. +We formulate a set of 'rules' for quick reference, while the prose +tries to motivate each of them. Do not always take them literally; +you should value good reasons for your actions higher than manpages +such as this one. SEPARATE CHANGES @@ -28,49 +30,68 @@ SEPARATE CHANGES As a general rule, you should try to split your changes into small logical steps, and commit each of them. They should be consistent, working independently of any later commits, pass the test suite, etc. +This makes the review process much easier, and the history much more +useful for later inspection and analysis, for example with +linkgit:git-blame[1] and linkgit:git-bisect[1]. -To achieve this, try to commit your new work at least every couple -hours. You can always go back and edit the commits with `git rebase ---interactive` to further improve the history before you publish it. +To achieve this, try to split your work into small steps from the very +beginning. It is always easier to squash a few commits together than +to split one big commit into several. Don't be afraid of making too +small or imperfect steps along the way. You can always go back later +and edit the commits with `git rebase \--interactive` before you +publish them. MANAGING BRANCHES ----------------- -In the following, we will assume there are 'developers', 'testers' and -'users'. Even if the "Testers" are actually an automated test suite -and all "Users" are developers themselves, try to think in these terms -as you follow a software change through its life cycle. +Usually a feature (or other change) evolves in stages: it "graduates" +from patch to the testing branches and on to stable releases. During +this process, it may require fixes or improvements. XXX terrible +paragraph XXX -Usually a change evolves in a few steps: +Merges (as opposed to cherry-picks, see below) greatly simplify +handling large numbers of commits, so a scalable workflow needs to use +merges. Fortunately Git is very good at merging. -* The developers implement a few iterations until it "seems to work". +XXX non sequitur XXX +In the following sections we discuss some problems that arise from +such a "change flow", and how to solve them with Git. -* The testers play with it, report bugs, test the fixes, eventually - clearing the change for stable releases. -* As the users work with the new feature, they report bugs which will - have to be fixed. +Graduation +~~~~~~~~~~ -In the following sections we discuss some problems that arise from -such a "change flow", and how to solve them with Git. +As a given feature goes from experimental to stable, it also +"graduates" between the corresponding branches of the software. +`git.git` uses the following 'main branches': + +* 'master' tracks the commits that should go into the next release; + +* 'maint' tracks the commits that should go into the next "maintenance + release", i.e., update of the last released stable version; and -We consider a fictional project with (supported) stable branch -'maint', main testing/development branch 'master' and "bleeding edge" -branch 'next'. We collectively call these three branches 'main -branches'. +* 'next' is intended as a testing branch for people who like to use + more experimental stuff. + +There is a fourth official branch that is used slightly differently: + +* 'pu' (proposed updates) is an integration branch for things that are + not quite ready for inclusion yet (see "Integration Branches" + below). + +Conceptually, the feature enters at an unstable branch (usually 'next' +or 'pu'), and "graduates" to 'master' for the next release once it is +considered stable enough. Merging upwards ~~~~~~~~~~~~~~~ -Since Git is quite good at merges, one should try to use them to -propagate changes. For example, if a bug is fixed, you would want to -apply the corresponding fix to all main branches. - -A quick moment of thought reveals that you cannot do this by merging -"downwards" to older releases, since that would merge 'all' changes. -Hence the following: +As explained above, features conceptually "graduate downwards" to +older releases. This cannot be done by actually merging downwards, +however, since that would merge 'all' changes on the unstable branch +into the stable one. Hence the following: .Merge upwards [caption="Rule: "] @@ -84,27 +105,31 @@ This gives a very controlled flow of fixes. If you notice that you have applied a fix to e.g. 'master' that is also required in 'maint', you will need to cherry-pick it (using linkgit:git-cherry-pick[1]) downwards. This will happen a few times and is nothing to worry about -unless you do it all the time. +unless you do it very frequently. Topic branches ~~~~~~~~~~~~~~ Any nontrivial feature will require several patches to implement, and -may get extra bugfixes or improvements during its lifetime. If all -such commits were in one long linear history chain (e.g., if they were -all committed directly to 'master'), it becomes very hard to see how -they belong together. +may get extra bugfixes or improvements during its lifetime. + +Committing everything directly on the main branches leads to many +problems: Bad commits cannot be undone, so they must be reverted one +by one, which creates confusing histories and further error potential +when you forget to revert part of a group of changes. Working in +parallel mixes up the changes, creating further confusion. The key concept here is "topic branches". The name is pretty self -explanatory, with a minor caveat that comes from the "merge upwards" -rule above: +explanatory, with a caveat that comes from the "merge upwards" rule +above: .Topic branches [caption="Rule: "] ===================================== -Make a side branch for every topic. Fork it off at the oldest main -branch that you will eventually want to merge it into. +Make a side branch for every topic (feature, bugfix, ...). Fork it off +at the oldest main branch that you will eventually want to merge it +into. ===================================== Many things can then be done very naturally: @@ -112,7 +137,7 @@ Many things can then be done very naturally: * To get the feature/bugfix into a main branch, simply merge it. If the topic has evolved further in the meantime, merge again. -* If you find you need new features from an 'other' branch to continue +* If you find you need new features from the branch 'other' to continue working on your topic, merge 'other' to 'topic'. (However, do not do this "just habitually", see below.) @@ -133,16 +158,17 @@ frowned upon: ===================================== Do not merge to downstream except: -* with a good reason (such as upstream API changes that affect you), or +* with a good reason: upstream API changes affect your branch; your + branch no longer merges to upstream cleanly; etc. * at well-defined points such as when an upstream release has been tagged. ===================================== Otherwise, the many resulting small merges will greatly clutter up history. Anyone who later investigates the history of a file will -have to find out whether that merge affected the topic in -development. Linus hates it. An upstream might even inadvertently be -merged into a "more stable" branch. And so on. +have to find out whether that merge affected the topic in development. +An upstream might even inadvertently be merged into a "more stable" +branch. And so on. Integration branches @@ -167,7 +193,9 @@ throw-away branch. If you make it (very) clear that this branch is going to be deleted right after the testing, you can even publish this branch, for example to give the testers a chance to work with it, or other developers a -chance to see if their in-progress work will be compatible. +chance to see if their in-progress work will be compatible. `git.git` +has such an official integration branch called 'pu'. You must never +base any work on such a throw-away branch! SHARING WORK @@ -177,17 +205,17 @@ After the last section, you should know how to manage topics. In general, you will not be the only person working on the project, so you will have to share your work. -Roughly speaking, there are two important workflows. Their -distinguishing mark is whether they can be used to propagate merges. -Medium to large projects will typically employ some mixture of the -two: +Roughly speaking, there are two important workflows: push/pull and +format-patch/am. The important difference is that push/pull can +propagate merges, while format-patch cannot. Medium to large projects +will typically employ some mixture of the two: * "Upstream" in the most general sense 'pushes' changes to the - repositor(ies) holding the main history. Everyone can 'pull' from - there to stay up to date. + repositor(ies) holding the official history of the project. + Everyone can 'fetch' from there to stay up to date. -* Frequent contributors, subsystem maintainers, etc. may use push/pull - to send their changes upstream. +* Frequent contributors, subsystem maintainers, etc. may push to a + public repository to make their changes available to upstream. * The rest -- typically anyone more than one or two levels away from the main maintainer -- send patches by mail. @@ -291,15 +319,15 @@ merge because you cannot format-patch merges): .format-patch/am: Keeping topics up to date [caption="Recipe: "] ===================================== -`git rebase upstream` +`git pull --rebase <url> <branch>` ===================================== You can then fix the conflicts during the rebase. Presumably you have not published your topic other than by mail, so rebasing it is not a problem. -If you receive such a patch (as maintainer, or perhaps reader of the -mailing list it was sent to), save the mail to a file and use +If you receive such a patch (as maintainer, or perhaps as a reader of +the mailing list it was sent to), save the mail to a file and use 'git-am': .format-patch/am: Publishing branches/topics @@ -309,9 +337,9 @@ mailing list it was sent to), save the mail to a file and use ===================================== One feature worth pointing out is the three-way merge, which can help -if you get conflicts because of renames: `git am -3` will use index -information contained in patches to reconstruct a merge base. See -linkgit:git-am[1] for other options. +if you get conflicts: `git am -3` will use index information contained +in patches to figure out the merge base. See linkgit:git-am[1] for +other options. SEE ALSO ^ permalink raw reply related [flat|nested] 29+ messages in thread
* Re: [RFC PATCH] Documentation: add manpage about workflows 2008-09-30 16:05 ` Thomas Rast 2008-09-30 16:07 ` Thomas Rast @ 2008-10-01 9:54 ` Santi Béjar 2008-10-09 11:42 ` [RFC PATCH v2] " Thomas Rast 1 sibling, 1 reply; 29+ messages in thread From: Santi Béjar @ 2008-10-01 9:54 UTC (permalink / raw) To: Thomas Rast; +Cc: Dmitry Potapov, git, Junio C Hamano On Tue, Sep 30, 2008 at 6:05 PM, Thomas Rast <trast@student.ethz.ch> wrote: > As a quick status update, mostly to show that I haven't forgotten > about this topic: > > Thanks Santi and Dmitry for your comments. You have raised some very > good points, and I attempted to fix these issues. Thanks for you document. > > Unfortunately, in some places I got stuck trying to work out good > explanations for the workings of git.git, and some of the newer > rearrangements left the lead of "Merging branches" in a dire state. > I'll see if I can find a good solution myself, but suggestions would > be welcome in any case. The WIP text is below, and I'll follow up > with an interdiff to the last version. > > - Thomas > [...] > > SEPARATE CHANGES > ---------------- > > As a general rule, you should try to split your changes into small > logical steps, and commit each of them. They should be consistent, > working independently of any later commits, pass the test suite, etc. > This makes the review process much easier, and the history much more > useful for later inspection and analysis, for example with > linkgit:git-blame[1] and linkgit:git-bisect[1]. > > To achieve this, try to split your work into small steps from the very > beginning. It is always easier to squash a few commits together than > to split one big commit into several. Don't be afraid of making too > small or imperfect steps along the way. You can always go back later > and edit the commits with `git rebase \--interactive` before you > publish them. > I know it is against the recommendation but I think it makes sense to explain how you can split big patches testing them as is explained in gitlink:git-stash. [...] > Graduation > ~~~~~~~~~~ > > As a given feature goes from experimental to stable, it also > "graduates" between the corresponding branches of the software. > `git.git` uses the following 'main branches': > > * 'master' tracks the commits that should go into the next release; > > * 'maint' tracks the commits that should go into the next "maintenance > release", i.e., update of the last released stable version; and The "logical" order would be 'maint', 'master', 'next', 'pu', each one should fast-forward to the next one. > > * 'next' is intended as a testing branch for people who like to use > more experimental stuff. The key point is not "more experimental stuff", but 'master' material but not stable enough. [...] > Integration branches > ~~~~~~~~~~~~~~~~~~~~ > > If you followed the last paragraph, you will now have many small topic > branches, and occasionally wonder how they interact. Perhaps the > result of merging them does not even work? But on the other hand, we > want to avoid merging them anywhere "stable" because such merges > cannot easily be undone. > > The solution, of course, is to make a merge that we can undo: merge > into a throw-away branch. > > .Integration branches > [caption="Rule: "] > ===================================== > To test the interaction of several topics, merge them into a > throw-away branch. > ===================================== > > If you make it (very) clear that this branch is going to be deleted > right after the testing, you can even publish this branch, for example > to give the testers a chance to work with it, or other developers a > chance to see if their in-progress work will be compatible. `git.git` > has such an official integration branch called 'pu'. You must never > base any work on such a throw-away branch! Maybe this last sentence should go in the "Rule:". > > > SHARING WORK > ------------ > > After the last section, you should know how to manage topics. In > general, you will not be the only person working on the project, so > you will have to share your work. Sharing work is explained in the tutorials, maybe this section should be about "distributed workflows". > > Roughly speaking, there are two important workflows: push/pull and > format-patch/am. A more descriptive name could be the "merge workflow" and the "patch workflow". > The important difference is that push/pull can > propagate merges, while format-patch cannot. Like I said in the other mail, the key is that one preserves the history (including merges) and the other not. This is what makes possible the push/pull workflow, that all the branches should fast-forward (and this should be said somewhere) > Medium to large projects > will typically employ some mixture of the two: s/:/./ Although I think it should be deleted. And what about litle projects? Different roles do uses different workflows: > > * "Upstream" in the most general sense 'pushes' changes to the > repositor(ies) holding the official history of the project. > Everyone can 'fetch' from there to stay up to date. s/pushes/publishes/ s/fetch/merge/ > > * Frequent contributors, subsystem maintainers, etc. may push to a > public repository to make their changes available to upstream. s/push/publish/ Or: * Frequent contributors, subsystem maintainers, etc. may publish to a public repository to make their changes available to upstream, or to their downstreams (acting as upstream to them) > > * The rest -- typically anyone more than one or two levels away from the > main maintainer -- send patches by mail. In the "distributed workflows" this would be: * "Upstream" merges the branches from subsystem maintainers, applies the 'patches' from others (including themselves) and publishes to the main repository. See link:howto/maintain-git.txt to see how it is done in git.git) * "Subsystem maintainers" act as "upstream" but publishes to a different repository/branch. * Frequent contributors, etc, publish their changes in another repository. * The rest ... > > None of these boundaries are sharp, so find out what works best for > you. > > > Push/pull > ~~~~~~~~~ > > There are three main tools that can be used for this: Sorry, but I don't see the point explaining how to publish the branches, or keep them up to date. > > If you are a maintainer and would like to merge other people's topic > branches to the main branches, they will typically send a request to > do so by mail. Such a request might say > > ------------------------------------- > Please pull from > git://some.server.somewhere/random/repo.git mytopic > ------------------------------------- > > In that case, 'git-pull' can do the fetch and merge in one go, as > follows. Or: Then, you can merge them with just: > .Push/pull: Merging remote topics > [caption="Recipe: "] > ===================================== > `git pull <url> <branch>` > ===================================== > Use "<url> <branch>" or "git://some.server.somewhere/random/repo.git mytopic" in the recipies, but not both. [...] > > format-patch/am > ~~~~~~~~~~~~~~~ s/.*/patch workflow/ > > If you are a contributor that sends changes upstream in the form of > emails, you should use topic branches as usual (see above). Then use > linkgit:git-format-patch[1] to generate the corresponding emails > (highly recommended over manually formatting them because it makes the > maintainer's life easier). > > .format-patch/am: Publishing branches/topics > [caption="Recipe: "] > ===================================== > * `git format-patch -M upstream..topic` to turn them into preformatted > patch files > * `git send-email --to=<recipient> <patches>` > ===================================== > > See the linkgit:git-format-patch[1] and linkgit:git-send-email[1] > manpages for further usage notes. Also you should be aware that the > maintainer may impose further restrictions, such as "Signed-off-by" > requirements. The restrictions and the Signed-off-by also applies to the other workflows. > > If the maintainer tells you that your patch no longer applies to the > current upstream, you will have to rebase your topic (you cannot use a > merge because you cannot format-patch merges): > > .format-patch/am: Keeping topics up to date > [caption="Recipe: "] > ===================================== > `git pull --rebase <url> <branch>` > ===================================== > > You can then fix the conflicts during the rebase. Presumably you have > not published your topic other than by mail, so rebasing it is not a > problem. > > If you receive such a patch (as maintainer, or perhaps as a reader of > the mailing list it was sent to), save the mail to a file and use > 'git-am': > > .format-patch/am: Publishing branches/topics > [caption="Recipe: "] > ===================================== > `git am < patch` > ===================================== > > One feature worth pointing out is the three-way merge, which can help > if you get conflicts: `git am -3` will use index information contained > in patches to figure out the merge base. See linkgit:git-am[1] for > other options. > > > SEE ALSO > -------- > linkgit:gittutorial[7], > linkgit:git-push[1], > linkgit:git-pull[1], > linkgit:git-merge[1], > linkgit:git-rebase[1], > linkgit:git-format-patch[1], > linkgit:git-send-email[1], > linkgit:git-am[1] > > GIT > --- > Part of the linkgit:git[1] suite. > > > ^ permalink raw reply [flat|nested] 29+ messages in thread
* [RFC PATCH v2] Documentation: add manpage about workflows 2008-10-01 9:54 ` Santi Béjar @ 2008-10-09 11:42 ` Thomas Rast 2008-10-09 11:42 ` [Interdiff] " Thomas Rast 2008-10-09 12:50 ` Junio C Hamano 0 siblings, 2 replies; 29+ messages in thread From: Thomas Rast @ 2008-10-09 11:42 UTC (permalink / raw) To: git; +Cc: santi, Dmitry Potapov, Junio C Hamano This attempts to make a manpage about workflows that is both handy to point people at it and as a beginner's introduction. Signed-off-by: Thomas Rast <trast@student.ethz.ch> --- [Apologies if some of the Cc's were sent twice; I got a bounce because of non-ASCII headers and was unable to tell if any were delivered.] Let's try another iteration. I decided the "MANAGING BRANCHES" introduction paragraph was a good place to (finally) mention the points about merge vs. cherry-pick raised by Dmitry earlier. I think I've addressed the other concerns, except for the "SHARING WORK" section, now renamed to "DISTRIBUTED WORKFLOWS": Santi Béjar wrote: > Sorry, but I don't see the point explaining how to publish the > branches, or keep them up to date. I feel it needs to be explained _somewhere_, since pull is designed to make the merge workflow as easy as possible, and then push/fetch are needed to complete the picture (especially so since I'm trying to make a point of highlighting when not to use pull). Maybe you can/want to convince me otherwise. And note that push is not explained in gittutorial.txt, only linked. It is explained in gitcore-tutorial.txt, but that says However, an understanding of these low-level tools can be helpful if you want to understand git's internals. in the introduction. I don't really expect any user to read any further after hearing that everything in there is "low-level". Maybe some tutorial cleanup would be in order. Other than that, I'll wait for some more comments, then polish up the commit message and submit "for real". Interdiff will follow, as before. - Thomas Documentation/Makefile | 2 +- Documentation/gitworkflows.txt | 362 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 363 insertions(+), 1 deletions(-) diff --git a/Documentation/Makefile b/Documentation/Makefile index ded0e40..e33ddcb 100644 --- a/Documentation/Makefile +++ b/Documentation/Makefile @@ -6,7 +6,7 @@ MAN5_TXT=gitattributes.txt gitignore.txt gitmodules.txt githooks.txt \ gitrepository-layout.txt MAN7_TXT=gitcli.txt gittutorial.txt gittutorial-2.txt \ gitcvs-migration.txt gitcore-tutorial.txt gitglossary.txt \ - gitdiffcore.txt + gitdiffcore.txt gitworkflows.txt MAN_TXT = $(MAN1_TXT) $(MAN5_TXT) $(MAN7_TXT) MAN_XML=$(patsubst %.txt,%.xml,$(MAN_TXT)) diff --git a/Documentation/gitworkflows.txt b/Documentation/gitworkflows.txt new file mode 100644 index 0000000..037ace5 --- /dev/null +++ b/Documentation/gitworkflows.txt @@ -0,0 +1,362 @@ +gitworkflows(7) +=============== + +NAME +---- +gitworkflows - An overview of recommended workflows with git + +SYNOPSIS +-------- +git * + + +DESCRIPTION +----------- + +This document attempts to write down and motivate some of the workflow +elements used for `git.git` itself. Many ideas apply in general, +though the full workflow is rarely required for smaller projects with +fewer people involved. + +We formulate a set of 'rules' for quick reference, while the prose +tries to motivate each of them. Do not always take them literally; +you should value good reasons for your actions higher than manpages +such as this one. + + +SEPARATE CHANGES +---------------- + +As a general rule, you should try to split your changes into small +logical steps, and commit each of them. They should be consistent, +working independently of any later commits, pass the test suite, etc. +This makes the review process much easier, and the history much more +useful for later inspection and analysis, for example with +linkgit:git-blame[1] and linkgit:git-bisect[1]. + +To achieve this, try to split your work into small steps from the very +beginning. It is always easier to squash a few commits together than +to split one big commit into several. Don't be afraid of making too +small or imperfect steps along the way. You can always go back later +and edit the commits with `git rebase \--interactive` before you +publish them. You can use `git stash save \--keep-index` to run the +test suite independent of other uncommitted changes; see the EXAMPLES +section of linkgit:git-stash[1]. + + +MANAGING BRANCHES +----------------- + +There are two main tools that can be used to include changes from one +branch on another: linkgit:git-merge[1] and +linkgit:git-cherry-pick[1]. + +Merges have many advantages, so we try to solve as many problems as +possible with merges alone. Cherry-picking is still occasionally +useful; see "Merging upwards" below for an example. + +Most importantly, merging works at the branch level, while +cherry-picking works at the commit level. This means that a merge can +carry over the changes from 1, 10, or 1000 commits with equal ease, +which in turn means the workflow scales much better to a large number +of contributors (and contributions). Merges are also easier to +understand because a merge commit is a "promise" that all changes from +all its parents are now included. + +There is a tradeoff of course: merges require a more careful branch +management. The following subsections discuss the important points. + + +Graduation +~~~~~~~~~~ + +As a given feature goes from experimental to stable, it also +"graduates" between the corresponding branches of the software. +`git.git` uses the following 'main branches': + +* 'maint' tracks the commits that should go into the next "maintenance + release", i.e., update of the last released stable version; + +* 'master' tracks the commits that should go into the next release; + +* 'next' is intended as a testing branch for topics not stable enough + for master yet. + +There is a fourth official branch that is used slightly differently: + +* 'pu' (proposed updates) is an integration branch for things that are + not quite ready for inclusion yet (see "Integration Branches" + below). + +Each of the four branches is usually a direct descendant of the one +above it. + +Conceptually, the feature enters at an unstable branch (usually 'next' +or 'pu'), and "graduates" to 'master' for the next release once it is +considered stable enough. + + +Merging upwards +~~~~~~~~~~~~~~~ + +The "downwards graduation" discussed above cannot be done by actually +merging downwards, however, since that would merge 'all' changes on +the unstable branch into the stable one. Hence the following: + +.Merge upwards +[caption="Rule: "] +===================================== +Always commit your fixes to the oldest supported branch that require +them. Then (periodically) merge the main branches upwards into each +other. +===================================== + +This gives a very controlled flow of fixes. If you notice that you +have applied a fix to e.g. 'master' that is also required in 'maint', +you will need to cherry-pick it (using linkgit:git-cherry-pick[1]) +downwards. This will happen a few times and is nothing to worry about +unless you do it very frequently. + + +Topic branches +~~~~~~~~~~~~~~ + +Any nontrivial feature will require several patches to implement, and +may get extra bugfixes or improvements during its lifetime. + +Committing everything directly on the main branches leads to many +problems: Bad commits cannot be undone, so they must be reverted one +by one, which creates confusing histories and further error potential +when you forget to revert part of a group of changes. Working in +parallel mixes up the changes, creating further confusion. + +The key concept here is "topic branches". The name is pretty self +explanatory, with a caveat that comes from the "merge upwards" rule +above: + +.Topic branches +[caption="Rule: "] +===================================== +Make a side branch for every topic (feature, bugfix, ...). Fork it off +at the oldest main branch that you will eventually want to merge it +into. +===================================== + +Many things can then be done very naturally: + +* To get the feature/bugfix into a main branch, simply merge it. If + the topic has evolved further in the meantime, merge again. + +* If you find you need new features from the branch 'other' to continue + working on your topic, merge 'other' to 'topic'. (However, do not + do this "just habitually", see below.) + +* If you find you forked off the wrong branch and want to move it + "back in time", use linkgit:git-rebase[1]. + +Note that the last two points clash: a topic that has been merged +elsewhere should not be rebased. See the section on RECOVERING FROM +UPSTREAM REBASE in linkgit:git-rebase[1]. + +We should point out that "habitually" (regularly for no real reason) +merging a main branch into your topics -- and by extension, merging +anything upstream into anything downstream on a regular basis -- is +frowned upon: + +.Merge to downstream only at well-defined points +[caption="Rule: "] +===================================== +Do not merge to downstream except: + +* with a good reason: upstream API changes affect your branch; your + branch no longer merges to upstream cleanly; etc. + +* at well-defined points such as when an upstream release has been tagged. +===================================== + +Otherwise, the many resulting small merges will greatly clutter up +history. Anyone who later investigates the history of a file will +have to find out whether that merge affected the topic in development. +An upstream might even inadvertently be merged into a "more stable" +branch. And so on. + + +Integration branches +~~~~~~~~~~~~~~~~~~~~ + +If you followed the last paragraph, you will now have many small topic +branches, and occasionally wonder how they interact. Perhaps the +result of merging them does not even work? But on the other hand, we +want to avoid merging them anywhere "stable" because such merges +cannot easily be undone. + +The solution, of course, is to make a merge that we can undo: merge +into a throw-away branch. + +.Integration branches +[caption="Rule: "] +===================================== +To test the interaction of several topics, merge them into a +throw-away branch. You must never base any work on such a branch! +===================================== + +If you make it (very) clear that this branch is going to be deleted +right after the testing, you can even publish this branch, for example +to give the testers a chance to work with it, or other developers a +chance to see if their in-progress work will be compatible. `git.git` +has such an official integration branch called 'pu'. + + +DISTRIBUTED WORKFLOWS +--------------------- + +After the last section, you should know how to manage topics. In +general, you will not be the only person working on the project, so +you will have to share your work. + +Roughly speaking, there are two important workflows: merge and patch. +The important difference is that the merge workflow can propagate full +history, including merges, while patches cannot. Both workflows can +be used in parallel: in `git.git`, only subsystem maintainers use +the merge workflow, while everyone else sends patches. + +Note that the maintainer(s) may impose restrictions, such as +"Signed-off-by" requirements, that all commits/patches submitted for +inclusion must adhere to. Consult your project's documentation for +more information. + + +Merge workflow +~~~~~~~~~~~~~~ + +The merge workflow works by copying branches between upstream and +downstream. Upstream can merge contributions into the official +history; downstream base their work on the official history. + +There are three main tools that can be used for this: + +* linkgit:git-push[1] copies your branches to a remote repository, + usually to one that can be read by all involved parties; + +* linkgit:git-fetch[1] that copies remote branches to your repository; + and + +* linkgit:git-pull[1] that does fetch and merge in one go. + +Note the last point. Do 'not' use 'git-pull' unless you actually want +to merge the remote branch. + +Getting changes out is easy: + +.Push/pull: Publishing branches/topics +[caption="Recipe: "] +===================================== +`git push <remote> <branch>` and tell everyone where they can fetch +from. +===================================== + +You will still have to tell people by other means, such as mail. (Git +provides the linkgit:request-pull[1] to send preformatted pull +requests to upstream maintainers to simplify this task.) + +If you just want to get the newest copies of the main branches, +staying up to date is easy too: + +.Push/pull: Staying up to date +[caption="Recipe: "] +===================================== +Use `git fetch <remote>` or `git remote update` to stay up to date. +===================================== + +Then simply fork your topic branches from the stable remotes as +explained earlier. + +If you are a maintainer and would like to merge other people's topic +branches to the main branches, they will typically send a request to +do so by mail. Such a request looks like + +------------------------------------- +Please pull from + <url> <branch> +------------------------------------- + +In that case, 'git-pull' can do the fetch and merge in one go, as +follows. + +.Push/pull: Merging remote topics +[caption="Recipe: "] +===================================== +`git pull <url> <branch>` +===================================== + +Occasionally, the maintainer may get merge conflicts when he tries to +pull changes from downstream. In this case, he can ask downstream to +do the merge and resolve the conflicts themselves (perhaps they will +know better how to resolve them). It is one of the rare cases where +downstream 'should' merge from upstream. + + +Patch workflow +~~~~~~~~~~~~~~ + +If you are a contributor that sends changes upstream in the form of +emails, you should use topic branches as usual (see above). Then use +linkgit:git-format-patch[1] to generate the corresponding emails +(highly recommended over manually formatting them because it makes the +maintainer's life easier). + +.format-patch/am: Publishing branches/topics +[caption="Recipe: "] +===================================== +* `git format-patch -M upstream..topic` to turn them into preformatted + patch files +* `git send-email --to=<recipient> <patches>` +===================================== + +See the linkgit:git-format-patch[1] and linkgit:git-send-email[1] +manpages for further usage notes. + +If the maintainer tells you that your patch no longer applies to the +current upstream, you will have to rebase your topic (you cannot use a +merge because you cannot format-patch merges): + +.format-patch/am: Keeping topics up to date +[caption="Recipe: "] +===================================== +`git pull --rebase <url> <branch>` +===================================== + +You can then fix the conflicts during the rebase. Presumably you have +not published your topic other than by mail, so rebasing it is not a +problem. + +If you receive such a patch series (as maintainer, or perhaps as a +reader of the mailing list it was sent to), save the mails to files, +create a new topic branch and use 'git-am' to import the commits: + +.format-patch/am: Importing patches +[caption="Recipe: "] +===================================== +`git am < patch` +===================================== + +One feature worth pointing out is the three-way merge, which can help +if you get conflicts: `git am -3` will use index information contained +in patches to figure out the merge base. See linkgit:git-am[1] for +other options. + + +SEE ALSO +-------- +linkgit:gittutorial[7], +linkgit:git-push[1], +linkgit:git-pull[1], +linkgit:git-merge[1], +linkgit:git-rebase[1], +linkgit:git-format-patch[1], +linkgit:git-send-email[1], +linkgit:git-am[1] + +GIT +--- +Part of the linkgit:git[1] suite. -- tg: (2de69d4..) t/doc-workflows (depends on: origin/master t/doc-rebase-warn t/doc-rebase-refer) ^ permalink raw reply related [flat|nested] 29+ messages in thread
* [Interdiff] [RFC PATCH v2] Documentation: add manpage about workflows 2008-10-09 11:42 ` [RFC PATCH v2] " Thomas Rast @ 2008-10-09 11:42 ` Thomas Rast 2008-10-09 12:50 ` Junio C Hamano 1 sibling, 0 replies; 29+ messages in thread From: Thomas Rast @ 2008-10-09 11:42 UTC (permalink / raw) To: git; +Cc: santi, Dmitry Potapov, Junio C Hamano --- I wrote: > Interdiff will follow, as before. diff --git a/Documentation/gitworkflows.txt b/Documentation/gitworkflows.txt index 87c2270..037ace5 100644 --- a/Documentation/gitworkflows.txt +++ b/Documentation/gitworkflows.txt @@ -39,24 +39,32 @@ beginning. It is always easier to squash a few commits together than to split one big commit into several. Don't be afraid of making too small or imperfect steps along the way. You can always go back later and edit the commits with `git rebase \--interactive` before you -publish them. +publish them. You can use `git stash save \--keep-index` to run the +test suite independent of other uncommitted changes; see the EXAMPLES +section of linkgit:git-stash[1]. MANAGING BRANCHES ----------------- -Usually a feature (or other change) evolves in stages: it "graduates" -from patch to the testing branches and on to stable releases. During -this process, it may require fixes or improvements. XXX terrible -paragraph XXX +There are two main tools that can be used to include changes from one +branch on another: linkgit:git-merge[1] and +linkgit:git-cherry-pick[1]. -Merges (as opposed to cherry-picks, see below) greatly simplify -handling large numbers of commits, so a scalable workflow needs to use -merges. Fortunately Git is very good at merging. +Merges have many advantages, so we try to solve as many problems as +possible with merges alone. Cherry-picking is still occasionally +useful; see "Merging upwards" below for an example. -XXX non sequitur XXX -In the following sections we discuss some problems that arise from -such a "change flow", and how to solve them with Git. +Most importantly, merging works at the branch level, while +cherry-picking works at the commit level. This means that a merge can +carry over the changes from 1, 10, or 1000 commits with equal ease, +which in turn means the workflow scales much better to a large number +of contributors (and contributions). Merges are also easier to +understand because a merge commit is a "promise" that all changes from +all its parents are now included. + +There is a tradeoff of course: merges require a more careful branch +management. The following subsections discuss the important points. Graduation @@ -66,13 +74,13 @@ As a given feature goes from experimental to stable, it also "graduates" between the corresponding branches of the software. `git.git` uses the following 'main branches': -* 'master' tracks the commits that should go into the next release; - * 'maint' tracks the commits that should go into the next "maintenance - release", i.e., update of the last released stable version; and + release", i.e., update of the last released stable version; -* 'next' is intended as a testing branch for people who like to use - more experimental stuff. +* 'master' tracks the commits that should go into the next release; + +* 'next' is intended as a testing branch for topics not stable enough + for master yet. There is a fourth official branch that is used slightly differently: @@ -80,6 +88,9 @@ There is a fourth official branch that is used slightly differently: not quite ready for inclusion yet (see "Integration Branches" below). +Each of the four branches is usually a direct descendant of the one +above it. + Conceptually, the feature enters at an unstable branch (usually 'next' or 'pu'), and "graduates" to 'master' for the next release once it is considered stable enough. @@ -88,10 +99,9 @@ considered stable enough. Merging upwards ~~~~~~~~~~~~~~~ -As explained above, features conceptually "graduate downwards" to -older releases. This cannot be done by actually merging downwards, -however, since that would merge 'all' changes on the unstable branch -into the stable one. Hence the following: +The "downwards graduation" discussed above cannot be done by actually +merging downwards, however, since that would merge 'all' changes on +the unstable branch into the stable one. Hence the following: .Merge upwards [caption="Rule: "] @@ -187,45 +197,41 @@ into a throw-away branch. [caption="Rule: "] ===================================== To test the interaction of several topics, merge them into a -throw-away branch. +throw-away branch. You must never base any work on such a branch! ===================================== If you make it (very) clear that this branch is going to be deleted right after the testing, you can even publish this branch, for example to give the testers a chance to work with it, or other developers a chance to see if their in-progress work will be compatible. `git.git` -has such an official integration branch called 'pu'. You must never -base any work on such a throw-away branch! +has such an official integration branch called 'pu'. -SHARING WORK ------------- +DISTRIBUTED WORKFLOWS +--------------------- After the last section, you should know how to manage topics. In general, you will not be the only person working on the project, so you will have to share your work. -Roughly speaking, there are two important workflows: push/pull and -format-patch/am. The important difference is that push/pull can -propagate merges, while format-patch cannot. Medium to large projects -will typically employ some mixture of the two: +Roughly speaking, there are two important workflows: merge and patch. +The important difference is that the merge workflow can propagate full +history, including merges, while patches cannot. Both workflows can +be used in parallel: in `git.git`, only subsystem maintainers use +the merge workflow, while everyone else sends patches. -* "Upstream" in the most general sense 'pushes' changes to the - repositor(ies) holding the official history of the project. - Everyone can 'fetch' from there to stay up to date. +Note that the maintainer(s) may impose restrictions, such as +"Signed-off-by" requirements, that all commits/patches submitted for +inclusion must adhere to. Consult your project's documentation for +more information. -* Frequent contributors, subsystem maintainers, etc. may push to a - public repository to make their changes available to upstream. - -* The rest -- typically anyone more than one or two levels away from the - main maintainer -- send patches by mail. - -None of these boundaries are sharp, so find out what works best for -you. +Merge workflow +~~~~~~~~~~~~~~ -Push/pull -~~~~~~~~~ +The merge workflow works by copying branches between upstream and +downstream. Upstream can merge contributions into the official +history; downstream base their work on the official history. There are three main tools that can be used for this: @@ -267,11 +273,11 @@ explained earlier. If you are a maintainer and would like to merge other people's topic branches to the main branches, they will typically send a request to -do so by mail. Such a request might say +do so by mail. Such a request looks like ------------------------------------- Please pull from - git://some.server.somewhere/random/repo.git mytopic + <url> <branch> ------------------------------------- In that case, 'git-pull' can do the fetch and merge in one go, as @@ -290,8 +296,8 @@ know better how to resolve them). It is one of the rare cases where downstream 'should' merge from upstream. -format-patch/am -~~~~~~~~~~~~~~~ +Patch workflow +~~~~~~~~~~~~~~ If you are a contributor that sends changes upstream in the form of emails, you should use topic branches as usual (see above). Then use @@ -308,9 +314,7 @@ maintainer's life easier). ===================================== See the linkgit:git-format-patch[1] and linkgit:git-send-email[1] -manpages for further usage notes. Also you should be aware that the -maintainer may impose further restrictions, such as "Signed-off-by" -requirements. +manpages for further usage notes. If the maintainer tells you that your patch no longer applies to the current upstream, you will have to rebase your topic (you cannot use a @@ -326,11 +330,11 @@ You can then fix the conflicts during the rebase. Presumably you have not published your topic other than by mail, so rebasing it is not a problem. -If you receive such a patch (as maintainer, or perhaps as a reader of -the mailing list it was sent to), save the mail to a file and use -'git-am': +If you receive such a patch series (as maintainer, or perhaps as a +reader of the mailing list it was sent to), save the mails to files, +create a new topic branch and use 'git-am' to import the commits: -.format-patch/am: Publishing branches/topics +.format-patch/am: Importing patches [caption="Recipe: "] ===================================== `git am < patch` ^ permalink raw reply related [flat|nested] 29+ messages in thread
* Re: [RFC PATCH v2] Documentation: add manpage about workflows 2008-10-09 11:42 ` [RFC PATCH v2] " Thomas Rast 2008-10-09 11:42 ` [Interdiff] " Thomas Rast @ 2008-10-09 12:50 ` Junio C Hamano 2008-10-19 15:20 ` [RFC PATCH v3] " Thomas Rast 1 sibling, 1 reply; 29+ messages in thread From: Junio C Hamano @ 2008-10-09 12:50 UTC (permalink / raw) To: Thomas Rast; +Cc: git, santi, Dmitry Potapov, Junio C Hamano Thomas Rast <trast@student.ethz.ch> writes: > diff --git a/Documentation/gitworkflows.txt b/Documentation/gitworkflows.txt > new file mode 100644 > index 0000000..037ace5 > --- /dev/null > +++ b/Documentation/gitworkflows.txt > @@ -0,0 +1,362 @@ > +gitworkflows(7) > +=============== > ... > +DESCRIPTION > +----------- > + > +This document attempts to write down and motivate some of the workflow > +elements used for `git.git` itself. Many ideas apply in general, > +though the full workflow is rarely required for smaller projects with > +fewer people involved. Hmm. Even though I have to wonder if the workflow used in git.git should be treated as a representative BCP. For one thing, git.git is on the smaller end of the spectrum (from the point of view of the size of the codebase, but not from the size of the contributor base), it is something we know well enough and probably is a good place to take examples from. > +Graduation > +~~~~~~~~~~ > + > +As a given feature goes from experimental to stable, it also > +"graduates" between the corresponding branches of the software. > +`git.git` uses the following 'main branches': > + > +* 'maint' tracks the commits that should go into the next "maintenance > + release", i.e., update of the last released stable version; > + > +* 'master' tracks the commits that should go into the next release; > + > +* 'next' is intended as a testing branch for topics not stable enough > + for master yet. s/not stable enough/being tested for stability/;s/ yet//; The point being that commits on next are deemed stable enough from code inspection but are kept out of master for a while because your maintainer wants to be extra careful. > +Topic branches > +~~~~~~~~~~~~~~ > + > +Any nontrivial feature will require several patches to implement, and > +may get extra bugfixes or improvements during its lifetime. > + > +Committing everything directly on the main branches leads to many > +problems: Bad commits cannot be undone, so they must be reverted one > +by one, which creates confusing histories and further error potential > +when you forget to revert part of a group of changes. Working in > +parallel mixes up the changes, creating further confusion. > + > +The key concept here is "topic branches". The name is pretty self > +explanatory, with a caveat that comes from the "merge upwards" rule > +above: I'd reword the first sentence --- Use of "Topic branches" solves these problems. > +We should point out that "habitually" (regularly for no real reason) > +merging a main branch into your topics -- and by extension, merging > +anything upstream into anything downstream on a regular basis -- is > +frowned upon: > + > +.Merge to downstream only at well-defined points > +[caption="Rule: "] > +===================================== > +Do not merge to downstream except: > + > +* with a good reason: upstream API changes affect your branch; your > + branch no longer merges to upstream cleanly; etc. > + > +* at well-defined points such as when an upstream release has been tagged. > +===================================== > + > +Otherwise, the many resulting small merges will greatly clutter up > +history. Anyone who later investigates the history of a file will > +have to find out whether that merge affected the topic in development. This description misses the most important reason why merging into topic branches is not a good idea. Once you merge a general purpose integration branch such as master into a topic branch, the branch ceases to be about the single topic. It becomes "the topic and other unrelated changes mixed together". > +Integration branches > +~~~~~~~~~~~~~~~~~~~~ Nomenclature. I think we use the word "integration branches" to mean the stable branches such as maint/master/next, not the ones you use for throw-away test merges. Always merging upward is a good rule, and this is when used with topic branches, there is one twist you did not mention but is worth knowing about. A topic that is meant to eventually merge into older integration branch (e.g. maint) does not necessarily have to be merged to its final destination branch first. I often do this: git checkout tr/maint-fix-bla maint git am -s fix-mail-from-thomas.txt git checkout next git merge tr/maint-fix-bla ... cook further, perhaps adding more commits to ... tr/maint-fix-bla topic and merging the result to next; ... and then when the topic appears to be stable do: git checkout master git merge tr/maint-fix-bla ... and later git checkout maint git merge tr/maint-fix-bla git branch -d tr/maint-fix-bla This keeps older integration branches stale, until the topic really gets proven to be regression-free in the field. This workflow is safer and more suitable for a final integration branch to which a known breakage is better than an unintended regression. An alternative would be what the reader would assume from your description of merging upwards, which would look like this: git checkout tr/maint-fix-bla maint git am -s fix-mail-from-thomas.txt git checkout maint git merge tr/maint-fix-bla git checkout master git merge maint git checkout next git merge master This can regress maint unintentionally and then the regression is propagated upwards to contaminate all integration branches. ^ permalink raw reply [flat|nested] 29+ messages in thread
* [RFC PATCH v3] Documentation: add manpage about workflows 2008-10-09 12:50 ` Junio C Hamano @ 2008-10-19 15:20 ` Thomas Rast 2008-10-19 15:20 ` [Interdiff] " Thomas Rast 2008-10-19 20:07 ` Junio C Hamano 0 siblings, 2 replies; 29+ messages in thread From: Thomas Rast @ 2008-10-19 15:20 UTC (permalink / raw) To: Junio C Hamano; +Cc: git, santi, Dmitry Potapov This attempts to make a manpage about workflows that is both handy to point people at it and as a beginner's introduction. Signed-off-by: Thomas Rast <trast@student.ethz.ch> --- > > +Integration branches > > +~~~~~~~~~~~~~~~~~~~~ > > Nomenclature. I think we use the word "integration branches" to mean the > stable branches such as maint/master/next, not the ones you use for > throw-away test merges. I renamed those, and now call 'pu' a "throw-away integration branch", which is sort of unwieldy but I can't think of a good short name. Full interdiff follows, as before. Documentation/Makefile | 2 +- Documentation/gitworkflows.txt | 364 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 365 insertions(+), 1 deletions(-) diff --git a/Documentation/Makefile b/Documentation/Makefile index ded0e40..e33ddcb 100644 --- a/Documentation/Makefile +++ b/Documentation/Makefile @@ -6,7 +6,7 @@ MAN5_TXT=gitattributes.txt gitignore.txt gitmodules.txt githooks.txt \ gitrepository-layout.txt MAN7_TXT=gitcli.txt gittutorial.txt gittutorial-2.txt \ gitcvs-migration.txt gitcore-tutorial.txt gitglossary.txt \ - gitdiffcore.txt + gitdiffcore.txt gitworkflows.txt MAN_TXT = $(MAN1_TXT) $(MAN5_TXT) $(MAN7_TXT) MAN_XML=$(patsubst %.txt,%.xml,$(MAN_TXT)) diff --git a/Documentation/gitworkflows.txt b/Documentation/gitworkflows.txt new file mode 100644 index 0000000..7fe9f72 --- /dev/null +++ b/Documentation/gitworkflows.txt @@ -0,0 +1,364 @@ +gitworkflows(7) +=============== + +NAME +---- +gitworkflows - An overview of recommended workflows with git + +SYNOPSIS +-------- +git * + + +DESCRIPTION +----------- + +This document attempts to write down and motivate some of the workflow +elements used for `git.git` itself. Many ideas apply in general, +though the full workflow is rarely required for smaller projects with +fewer people involved. + +We formulate a set of 'rules' for quick reference, while the prose +tries to motivate each of them. Do not always take them literally; +you should value good reasons for your actions higher than manpages +such as this one. + + +SEPARATE CHANGES +---------------- + +As a general rule, you should try to split your changes into small +logical steps, and commit each of them. They should be consistent, +working independently of any later commits, pass the test suite, etc. +This makes the review process much easier, and the history much more +useful for later inspection and analysis, for example with +linkgit:git-blame[1] and linkgit:git-bisect[1]. + +To achieve this, try to split your work into small steps from the very +beginning. It is always easier to squash a few commits together than +to split one big commit into several. Don't be afraid of making too +small or imperfect steps along the way. You can always go back later +and edit the commits with `git rebase \--interactive` before you +publish them. You can use `git stash save \--keep-index` to run the +test suite independent of other uncommitted changes; see the EXAMPLES +section of linkgit:git-stash[1]. + + +MANAGING BRANCHES +----------------- + +There are two main tools that can be used to include changes from one +branch on another: linkgit:git-merge[1] and +linkgit:git-cherry-pick[1]. + +Merges have many advantages, so we try to solve as many problems as +possible with merges alone. Cherry-picking is still occasionally +useful; see "Merging upwards" below for an example. + +Most importantly, merging works at the branch level, while +cherry-picking works at the commit level. This means that a merge can +carry over the changes from 1, 10, or 1000 commits with equal ease, +which in turn means the workflow scales much better to a large number +of contributors (and contributions). Merges are also easier to +understand because a merge commit is a "promise" that all changes from +all its parents are now included. + +There is a tradeoff of course: merges require a more careful branch +management. The following subsections discuss the important points. + + +Graduation +~~~~~~~~~~ + +As a given feature goes from experimental to stable, it also +"graduates" between the corresponding branches of the software. +`git.git` uses the following 'integration branches': + +* 'maint' tracks the commits that should go into the next "maintenance + release", i.e., update of the last released stable version; + +* 'master' tracks the commits that should go into the next release; + +* 'next' is intended as a testing branch for topics being tested for + stability for master. + +There is a fourth official branch that is used slightly differently: + +* 'pu' (proposed updates) is an integration branch for things that are + not quite ready for inclusion yet (see "Integration Branches" + below). + +Each of the four branches is usually a direct descendant of the one +above it. + +Conceptually, the feature enters at an unstable branch (usually 'next' +or 'pu'), and "graduates" to 'master' for the next release once it is +considered stable enough. + + +Merging upwards +~~~~~~~~~~~~~~~ + +The "downwards graduation" discussed above cannot be done by actually +merging downwards, however, since that would merge 'all' changes on +the unstable branch into the stable one. Hence the following: + +.Merge upwards +[caption="Rule: "] +===================================== +Always commit your fixes to the oldest supported branch that require +them. Then (periodically) merge the integration branches upwards into each +other. +===================================== + +This gives a very controlled flow of fixes. If you notice that you +have applied a fix to e.g. 'master' that is also required in 'maint', +you will need to cherry-pick it (using linkgit:git-cherry-pick[1]) +downwards. This will happen a few times and is nothing to worry about +unless you do it very frequently. + + +Topic branches +~~~~~~~~~~~~~~ + +Any nontrivial feature will require several patches to implement, and +may get extra bugfixes or improvements during its lifetime. + +Committing everything directly on the integration branches leads to many +problems: Bad commits cannot be undone, so they must be reverted one +by one, which creates confusing histories and further error potential +when you forget to revert part of a group of changes. Working in +parallel mixes up the changes, creating further confusion. + +Use of "topic branches" solves these problems. The name is pretty +self explanatory, with a caveat that comes from the "merge upwards" +rule above: + +.Topic branches +[caption="Rule: "] +===================================== +Make a side branch for every topic (feature, bugfix, ...). Fork it off +at the oldest integration branch that you will eventually want to merge it +into. +===================================== + +Many things can then be done very naturally: + +* To get the feature/bugfix into an integration branch, simply merge + it. If the topic has evolved further in the meantime, merge again. + (Note that you do not necessarily have to merge it to the oldest + integration branch first. For example, you can first merge a bugfix + to 'next', give it some testing time, and merge to 'maint' when you + know it is stable.) + +* If you find you need new features from the branch 'other' to continue + working on your topic, merge 'other' to 'topic'. (However, do not + do this "just habitually", see below.) + +* If you find you forked off the wrong branch and want to move it + "back in time", use linkgit:git-rebase[1]. + +Note that the last point clashes with the other two: a topic that has +been merged elsewhere should not be rebased. See the section on +RECOVERING FROM UPSTREAM REBASE in linkgit:git-rebase[1]. + +We should point out that "habitually" (regularly for no real reason) +merging an integration branch into your topics -- and by extension, +merging anything upstream into anything downstream on a regular basis +-- is frowned upon: + +.Merge to downstream only at well-defined points +[caption="Rule: "] +===================================== +Do not merge to downstream except with a good reason: upstream API +changes affect your branch; your branch no longer merges to upstream +cleanly; etc. +===================================== + +Otherwise, the topic that was merged to suddenly contains more than a +single (well-separated) change. The many resulting small merges will +greatly clutter up history. Anyone who later investigates the history +of a file will have to find out whether that merge affected the topic +in development. An upstream might even inadvertently be merged into a +"more stable" branch. And so on. + + +Throw-away integration +~~~~~~~~~~~~~~~~~~~~~~ + +If you followed the last paragraph, you will now have many small topic +branches, and occasionally wonder how they interact. Perhaps the +result of merging them does not even work? But on the other hand, we +want to avoid merging them anywhere "stable" because such merges +cannot easily be undone. + +The solution, of course, is to make a merge that we can undo: merge +into a throw-away branch. + +.Throw-away integration branches +[caption="Rule: "] +===================================== +To test the interaction of several topics, merge them into a +throw-away branch. You must never base any work on such a branch! +===================================== + +If you make it (very) clear that this branch is going to be deleted +right after the testing, you can even publish this branch, for example +to give the testers a chance to work with it, or other developers a +chance to see if their in-progress work will be compatible. `git.git` +has such an official throw-away integration branch called 'pu'. + + +DISTRIBUTED WORKFLOWS +--------------------- + +After the last section, you should know how to manage topics. In +general, you will not be the only person working on the project, so +you will have to share your work. + +Roughly speaking, there are two important workflows: merge and patch. +The important difference is that the merge workflow can propagate full +history, including merges, while patches cannot. Both workflows can +be used in parallel: in `git.git`, only subsystem maintainers use +the merge workflow, while everyone else sends patches. + +Note that the maintainer(s) may impose restrictions, such as +"Signed-off-by" requirements, that all commits/patches submitted for +inclusion must adhere to. Consult your project's documentation for +more information. + + +Merge workflow +~~~~~~~~~~~~~~ + +The merge workflow works by copying branches between upstream and +downstream. Upstream can merge contributions into the official +history; downstream base their work on the official history. + +There are three main tools that can be used for this: + +* linkgit:git-push[1] copies your branches to a remote repository, + usually to one that can be read by all involved parties; + +* linkgit:git-fetch[1] that copies remote branches to your repository; + and + +* linkgit:git-pull[1] that does fetch and merge in one go. + +Note the last point. Do 'not' use 'git-pull' unless you actually want +to merge the remote branch. + +Getting changes out is easy: + +.Push/pull: Publishing branches/topics +[caption="Recipe: "] +===================================== +`git push <remote> <branch>` and tell everyone where they can fetch +from. +===================================== + +You will still have to tell people by other means, such as mail. (Git +provides the linkgit:request-pull[1] to send preformatted pull +requests to upstream maintainers to simplify this task.) + +If you just want to get the newest copies of the integration branches, +staying up to date is easy too: + +.Push/pull: Staying up to date +[caption="Recipe: "] +===================================== +Use `git fetch <remote>` or `git remote update` to stay up to date. +===================================== + +Then simply fork your topic branches from the stable remotes as +explained earlier. + +If you are a maintainer and would like to merge other people's topic +branches to the integration branches, they will typically send a +request to do so by mail. Such a request looks like + +------------------------------------- +Please pull from + <url> <branch> +------------------------------------- + +In that case, 'git-pull' can do the fetch and merge in one go, as +follows. + +.Push/pull: Merging remote topics +[caption="Recipe: "] +===================================== +`git pull <url> <branch>` +===================================== + +Occasionally, the maintainer may get merge conflicts when he tries to +pull changes from downstream. In this case, he can ask downstream to +do the merge and resolve the conflicts themselves (perhaps they will +know better how to resolve them). It is one of the rare cases where +downstream 'should' merge from upstream. + + +Patch workflow +~~~~~~~~~~~~~~ + +If you are a contributor that sends changes upstream in the form of +emails, you should use topic branches as usual (see above). Then use +linkgit:git-format-patch[1] to generate the corresponding emails +(highly recommended over manually formatting them because it makes the +maintainer's life easier). + +.format-patch/am: Publishing branches/topics +[caption="Recipe: "] +===================================== +* `git format-patch -M upstream..topic` to turn them into preformatted + patch files +* `git send-email --to=<recipient> <patches>` +===================================== + +See the linkgit:git-format-patch[1] and linkgit:git-send-email[1] +manpages for further usage notes. + +If the maintainer tells you that your patch no longer applies to the +current upstream, you will have to rebase your topic (you cannot use a +merge because you cannot format-patch merges): + +.format-patch/am: Keeping topics up to date +[caption="Recipe: "] +===================================== +`git pull --rebase <url> <branch>` +===================================== + +You can then fix the conflicts during the rebase. Presumably you have +not published your topic other than by mail, so rebasing it is not a +problem. + +If you receive such a patch series (as maintainer, or perhaps as a +reader of the mailing list it was sent to), save the mails to files, +create a new topic branch and use 'git-am' to import the commits: + +.format-patch/am: Importing patches +[caption="Recipe: "] +===================================== +`git am < patch` +===================================== + +One feature worth pointing out is the three-way merge, which can help +if you get conflicts: `git am -3` will use index information contained +in patches to figure out the merge base. See linkgit:git-am[1] for +other options. + + +SEE ALSO +-------- +linkgit:gittutorial[7], +linkgit:git-push[1], +linkgit:git-pull[1], +linkgit:git-merge[1], +linkgit:git-rebase[1], +linkgit:git-format-patch[1], +linkgit:git-send-email[1], +linkgit:git-am[1] + +GIT +--- +Part of the linkgit:git[1] suite. -- tg: (50ea8e5..) t/doc-workflows (depends on: origin/master t/doc-rebase-warn t/doc-rebase-refer) ^ permalink raw reply related [flat|nested] 29+ messages in thread
* [Interdiff] [RFC PATCH v3] Documentation: add manpage about workflows 2008-10-19 15:20 ` [RFC PATCH v3] " Thomas Rast @ 2008-10-19 15:20 ` Thomas Rast 2008-10-19 20:07 ` Junio C Hamano 1 sibling, 0 replies; 29+ messages in thread From: Thomas Rast @ 2008-10-19 15:20 UTC (permalink / raw) To: Junio C Hamano; +Cc: git, santi, Dmitry Potapov --- Documentation/gitworkflows.txt | 72 ++++++++++++++++++++------------------- 1 files changed, 37 insertions(+), 35 deletions(-) diff --git a/Documentation/gitworkflows.txt b/Documentation/gitworkflows.txt index 037ace5..7fe9f72 100644 --- a/Documentation/gitworkflows.txt +++ b/Documentation/gitworkflows.txt @@ -72,15 +72,15 @@ Graduation As a given feature goes from experimental to stable, it also "graduates" between the corresponding branches of the software. -`git.git` uses the following 'main branches': +`git.git` uses the following 'integration branches': * 'maint' tracks the commits that should go into the next "maintenance release", i.e., update of the last released stable version; * 'master' tracks the commits that should go into the next release; -* 'next' is intended as a testing branch for topics not stable enough - for master yet. +* 'next' is intended as a testing branch for topics being tested for + stability for master. There is a fourth official branch that is used slightly differently: @@ -107,7 +107,7 @@ the unstable branch into the stable one. Hence the following: [caption="Rule: "] ===================================== Always commit your fixes to the oldest supported branch that require -them. Then (periodically) merge the main branches upwards into each +them. Then (periodically) merge the integration branches upwards into each other. ===================================== @@ -124,28 +124,32 @@ Topic branches Any nontrivial feature will require several patches to implement, and may get extra bugfixes or improvements during its lifetime. -Committing everything directly on the main branches leads to many +Committing everything directly on the integration branches leads to many problems: Bad commits cannot be undone, so they must be reverted one by one, which creates confusing histories and further error potential when you forget to revert part of a group of changes. Working in parallel mixes up the changes, creating further confusion. -The key concept here is "topic branches". The name is pretty self -explanatory, with a caveat that comes from the "merge upwards" rule -above: +Use of "topic branches" solves these problems. The name is pretty +self explanatory, with a caveat that comes from the "merge upwards" +rule above: .Topic branches [caption="Rule: "] ===================================== Make a side branch for every topic (feature, bugfix, ...). Fork it off -at the oldest main branch that you will eventually want to merge it +at the oldest integration branch that you will eventually want to merge it into. ===================================== Many things can then be done very naturally: -* To get the feature/bugfix into a main branch, simply merge it. If - the topic has evolved further in the meantime, merge again. +* To get the feature/bugfix into an integration branch, simply merge + it. If the topic has evolved further in the meantime, merge again. + (Note that you do not necessarily have to merge it to the oldest + integration branch first. For example, you can first merge a bugfix + to 'next', give it some testing time, and merge to 'maint' when you + know it is stable.) * If you find you need new features from the branch 'other' to continue working on your topic, merge 'other' to 'topic'. (However, do not @@ -154,35 +158,33 @@ Many things can then be done very naturally: * If you find you forked off the wrong branch and want to move it "back in time", use linkgit:git-rebase[1]. -Note that the last two points clash: a topic that has been merged -elsewhere should not be rebased. See the section on RECOVERING FROM -UPSTREAM REBASE in linkgit:git-rebase[1]. +Note that the last point clashes with the other two: a topic that has +been merged elsewhere should not be rebased. See the section on +RECOVERING FROM UPSTREAM REBASE in linkgit:git-rebase[1]. We should point out that "habitually" (regularly for no real reason) -merging a main branch into your topics -- and by extension, merging -anything upstream into anything downstream on a regular basis -- is -frowned upon: +merging an integration branch into your topics -- and by extension, +merging anything upstream into anything downstream on a regular basis +-- is frowned upon: .Merge to downstream only at well-defined points [caption="Rule: "] ===================================== -Do not merge to downstream except: - -* with a good reason: upstream API changes affect your branch; your - branch no longer merges to upstream cleanly; etc. - -* at well-defined points such as when an upstream release has been tagged. +Do not merge to downstream except with a good reason: upstream API +changes affect your branch; your branch no longer merges to upstream +cleanly; etc. ===================================== -Otherwise, the many resulting small merges will greatly clutter up -history. Anyone who later investigates the history of a file will -have to find out whether that merge affected the topic in development. -An upstream might even inadvertently be merged into a "more stable" -branch. And so on. +Otherwise, the topic that was merged to suddenly contains more than a +single (well-separated) change. The many resulting small merges will +greatly clutter up history. Anyone who later investigates the history +of a file will have to find out whether that merge affected the topic +in development. An upstream might even inadvertently be merged into a +"more stable" branch. And so on. -Integration branches -~~~~~~~~~~~~~~~~~~~~ +Throw-away integration +~~~~~~~~~~~~~~~~~~~~~~ If you followed the last paragraph, you will now have many small topic branches, and occasionally wonder how they interact. Perhaps the @@ -193,7 +195,7 @@ cannot easily be undone. The solution, of course, is to make a merge that we can undo: merge into a throw-away branch. -.Integration branches +.Throw-away integration branches [caption="Rule: "] ===================================== To test the interaction of several topics, merge them into a @@ -204,7 +206,7 @@ If you make it (very) clear that this branch is going to be deleted right after the testing, you can even publish this branch, for example to give the testers a chance to work with it, or other developers a chance to see if their in-progress work will be compatible. `git.git` -has such an official integration branch called 'pu'. +has such an official throw-away integration branch called 'pu'. DISTRIBUTED WORKFLOWS @@ -259,7 +261,7 @@ You will still have to tell people by other means, such as mail. (Git provides the linkgit:request-pull[1] to send preformatted pull requests to upstream maintainers to simplify this task.) -If you just want to get the newest copies of the main branches, +If you just want to get the newest copies of the integration branches, staying up to date is easy too: .Push/pull: Staying up to date @@ -272,8 +274,8 @@ Then simply fork your topic branches from the stable remotes as explained earlier. If you are a maintainer and would like to merge other people's topic -branches to the main branches, they will typically send a request to -do so by mail. Such a request looks like +branches to the integration branches, they will typically send a +request to do so by mail. Such a request looks like ------------------------------------- Please pull from -- 1.6.0.2.916.g8e7f4 ^ permalink raw reply related [flat|nested] 29+ messages in thread
* Re: [RFC PATCH v3] Documentation: add manpage about workflows 2008-10-19 15:20 ` [RFC PATCH v3] " Thomas Rast 2008-10-19 15:20 ` [Interdiff] " Thomas Rast @ 2008-10-19 20:07 ` Junio C Hamano 1 sibling, 0 replies; 29+ messages in thread From: Junio C Hamano @ 2008-10-19 20:07 UTC (permalink / raw) To: Thomas Rast; +Cc: git, santi, Dmitry Potapov Thomas Rast <trast@student.ethz.ch> writes: > This attempts to make a manpage about workflows that is both handy to > point people at it and as a beginner's introduction. Is this still "RFC PATCH" or meant for application? I did not find many things that I find objectionable. On the other hand, I am not a good person to judge if this documentation is easily understandable by beginners (anymore). Do others who interact regularly with new people have comments? ^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [PATCH 1/2] Documentation: new upstream rebase recovery section in git-rebase 2008-09-11 15:38 ` [PATCH 1/2] " Thomas Rast 2008-09-11 15:38 ` [PATCH 2/2] Documentation: Refer to git-rebase(1) to warn against rewriting Thomas Rast @ 2008-09-12 1:15 ` Marcus Griep 2008-09-13 5:08 ` Junio C Hamano 2 siblings, 0 replies; 29+ messages in thread From: Marcus Griep @ 2008-09-12 1:15 UTC (permalink / raw) To: Thomas Rast; +Cc: git, Junio C Hamano [-- Attachment #1: Type: text/plain, Size: 1120 bytes --] Thomas Rast wrote: > +Now suppose the 'subsystem' maintainer decides to clean up his history > +with an interactive rebase. He edits commits A and D (marked with a > +`*`), decides to remove D entirely and moves B to the front. This > +results in Minor correction: -+with an interactive rebase. He edits commits A and D (marked with a ++with an interactive rebase. He edits commits A and C (marked with a > +To fix this, you have to manually transplant your own part of the > +history to the new branch head. Looking at `git log`, you should be > +able to determine that three commits on 'topic' are yours. Again > +assuming you are already on 'topic', you can do > +------------ > + git rebase --onto subsystem HEAD~3 > +------------ > +to put things right. Of course, this again ripples onwards: > +'everyone' downstream from 'subsystem' will have to 'manually' rebase > +all their work! I like this documentation because it provides another clear case of how the '--onto' option is used. -- Marcus Griep GPG Key ID: 0x5E968152 —— http://www.boohaunt.net את.ψο´ [-- Attachment #2: OpenPGP digital signature --] [-- Type: application/pgp-signature, Size: 793 bytes --] ^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [PATCH 1/2] Documentation: new upstream rebase recovery section in git-rebase 2008-09-11 15:38 ` [PATCH 1/2] " Thomas Rast 2008-09-11 15:38 ` [PATCH 2/2] Documentation: Refer to git-rebase(1) to warn against rewriting Thomas Rast 2008-09-12 1:15 ` [PATCH 1/2] Documentation: new upstream rebase recovery section in git-rebase Marcus Griep @ 2008-09-13 5:08 ` Junio C Hamano 2008-09-13 16:10 ` [PATCH 0/3] Documentation: rebase and workflows Thomas Rast 2 siblings, 1 reply; 29+ messages in thread From: Junio C Hamano @ 2008-09-13 5:08 UTC (permalink / raw) To: Thomas Rast; +Cc: git Thomas Rast <trast@student.ethz.ch> writes: > +RECOVERING FROM UPSTREAM REBASE > +------------------------------- > + > +This section briefly explains the problems that arise from rebasing or > +rewriting published branches, and shows how to recover. The largest issue of "The problem" is that the person who rebases causes this problem to others, _forcing_ his downstream to recover. This intro needs to make it clear the distinction between the person who rebases, who suffers is forced to recover as the consequence. > + o---o---o---o---o master > + \ > + o---o---o---o---o subsystem > + \ > + *---*---* topic >... > +If 'subsystem' is rebased against master, the following happens: >... > + o---o---o---o---o master > + | \ > + | o'--o'--o'--o'--o' subsystem > + \ > + o---o---o---o---o---*---*---* topic Make the original upstream a bit longer in the "after" picture, explaining that "your upstream subsystem rebased on top of its own upstream after it gets updated", so that the part that are unchanged in two pictures are not drawn differently like you did above. In other words, draw it like this. It is much easier to see what's changed and what's unchanged, if the part that hasn't changed stayed unchanged in the picture: o---o---o---o---o master \ o---o---o---o---o subsystem \ *---*---* topic o---o---o---o---o---o---o---o master \ \ o---o---o---o---o o'--o'--o'--o'--o' subsystem \ *---*---* topic > +Note that while we have marked your own commits with a '*', there is > +nothing that distinguishes them from the commits that previously were > +on 'subsystem'. Luckily, 'git-rebase' knows to skip commits that are > +textually the same as commits in the upstream. So if you say > +(assuming you're on 'topic') There is no luck involved in "git rebase" knowing how to do this -- this is by design. But more importantly, at this point, there is a break in the flow of thought in this section. Step back and read what you wrote, pretending as if you are reading the section for the first time, and notice: * The readers were shown how the topology before and after the subsystem's rebase looked like; * The readers haven't been told what you are trying teach them now. Yes, I know that you are going to tell them how to transplant their own commits on top of updated subsystem, but they don't know that yet; * Some of the readers may not even understand why it is a bad idea to keep building on top of the old subsystem without rebasing on top of the rebased subsystem at this point. Only when the readers know that the objective is to transplant these three top commits, they would start appreciating the difficulty (i.e. you cannot tell the commits apart by looking at the topology alone) of rebase the reader has to do, and the smart (i.e. if you are lucky, the rebase your upstream did may have been a simple one) git-rebase uses to help them. It would suffice to insert something like this before "Note that...". To continue working from here, you need to transplant your own commits (marked as '*') on top of the "subsystem", which is now rebased. But see footnote below. > +This becomes a ripple effect to anyone downstream of the first rebase: > +anyone downstream from 'topic' now needs to rebase too, and so on. This calls for a stronger wording than "needs to", perhaps "forced to". > +Things get more complicated if your upstream used `git rebase > +--interactive` (or `commit --amend` or `reset --hard HEAD^`). I do not think this section is absolutely necessary. The upstream may have done a simple rebase, which may have conflicted with the changes in its own upstream. > +To fix this, you have to manually transplant your own part of the > +history to the new branch head. Looking at `git log`, you should be > +able to determine that three commits on 'topic' are yours. Again > +assuming you are already on 'topic', you can do > +------------ > + git rebase --onto subsystem HEAD~3 > +------------ > +to put things right. HEAD~3 would _work_, but it often is easier to visualize this (perhaps in your head, or in "gitk HEAD origin origin@{1}"): o---o---o---o---o---o---o---o master \ \ o---o---o---o---o o'--o'--o'--o'--o' subsystem \ *---*---* topic and say: $ git rebase --onto subsystem subsystem@{1} The reflog reference "1" may be larger depending on the number of times you fetched from them without rebasing, though. [Footnote] You did not cover why midstream rebase _forces_ downstream to rebase. If the leaf-level person did not know better, or did not care, starting from this topology: o---o---o---o---o---o---o---o master \ \ o---o---o---o---o o'--o'--o'--o'--o' subsystem \ *---*---* topic the leaf person can keep building on top of the old topic, and later when the topic is mature, have subsystem merge the result. If the rebase the subsystem did was simple enough, the merge will be easy to resolve (both sides modifying the same way). o---o---o---o---o---o---o---o master \ \ o---o---o---o---o o'--o'--o'--o'--o'--M subsystem \ / *---*---*---*---*---*---* The problem is that the resulting history will keep two copies of the morally equivalent commits from the subsystem. You know that, and I know that, but the purpose of the document is to explain it to people who do not know it yet. ^ permalink raw reply [flat|nested] 29+ messages in thread
* [PATCH 0/3] Documentation: rebase and workflows 2008-09-13 5:08 ` Junio C Hamano @ 2008-09-13 16:10 ` Thomas Rast 2008-09-13 16:11 ` [PATCH 1/3] Documentation: new upstream rebase recovery section in git-rebase Thomas Rast 0 siblings, 1 reply; 29+ messages in thread From: Thomas Rast @ 2008-09-13 16:10 UTC (permalink / raw) To: git; +Cc: Junio C Hamano Junio C Hamano wrote: > First of all, thanks for your excellent criticism of my patch. (Thanks also to Marcus for spotting the typo, though I eventually decided to remove the corresponding part again.) I'm rerolling the entire series, with a few improvements to 3/3, and following that with an interdiff. 1/3 is almost a complete rewrite. (I realise that 3/3 is not really related to the first two, so we may eventually have to split it off the series if it takes more time.) All snipped comments have been addressed ... hopefully ;-) > In other words, draw it like this. It is much easier to see what's > changed and what's unchanged, if the part that hasn't changed stayed > unchanged in the picture: [...] > o---o---o---o---o---o---o---o master > \ \ > o---o---o---o---o o'--o'--o'--o'--o' subsystem > \ > *---*---* topic I had the old one in the other style to emphasise that all commits on 'topic' are "indistinguishable" w.r.t. source. But this indeed makes for nicer graphs. > Thomas Rast <trast@student.ethz.ch> writes: > > +on 'subsystem'. Luckily, 'git-rebase' knows to skip commits that are > > +textually the same as commits in the upstream. So if you say > > There is no luck involved in "git rebase" knowing how to do this -- this > is by design. Luckily for the user! :-) > But more importantly, at this point, there is a break in the flow of > thought in this section. Step back and read what you wrote, pretending as > if you are reading the section for the first time, and notice: [...] Indeed, you are right. I stole your "merge without rebase" drawing, and added a paragraph about the reasons for a rebase. However: > The problem is that the resulting history will keep two copies of the > morally equivalent commits from the subsystem. You know that, and I know > that, but the purpose of the document is to explain it to people who do > not know it yet. Maybe that's just me, but I always thought the duplication argument was a bit weak. I think reasons such as "resurrects changes that have been (presumably for a reason) undone" are far scarier and more likely to stop users from rebasing. Eventually, I omitted it to keep the justification paragraph shorter, but if others feel the same, maybe it should go in. - Thomas Thomas Rast (3): Documentation: new upstream rebase recovery section in git-rebase Documentation: Refer to git-rebase(1) to warn against rewriting Documentation: add manpage about workflows Documentation/Makefile | 2 +- Documentation/git-commit.txt | 4 + Documentation/git-filter-branch.txt | 4 +- Documentation/git-rebase.txt | 129 +++++++++++++- Documentation/git-reset.txt | 4 +- Documentation/gitworkflows.txt | 330 +++++++++++++++++++++++++++++++++++ 6 files changed, 465 insertions(+), 8 deletions(-) create mode 100644 Documentation/gitworkflows.txt ^ permalink raw reply [flat|nested] 29+ messages in thread
* [PATCH 1/3] Documentation: new upstream rebase recovery section in git-rebase 2008-09-13 16:10 ` [PATCH 0/3] Documentation: rebase and workflows Thomas Rast @ 2008-09-13 16:11 ` Thomas Rast 2008-09-13 16:11 ` [PATCH 2/3] Documentation: Refer to git-rebase(1) to warn against rewriting Thomas Rast 0 siblings, 1 reply; 29+ messages in thread From: Thomas Rast @ 2008-09-13 16:11 UTC (permalink / raw) To: git; +Cc: Junio C Hamano Documents how to recover if the upstream that you pull from has rebased the branches you depend your work on. Hopefully this can also serve as a warning to potential rebasers. Signed-off-by: Thomas Rast <trast@student.ethz.ch> --- See the series leader for discussion. Documentation/git-rebase.txt | 129 ++++++++++++++++++++++++++++++++++++++++-- 1 files changed, 124 insertions(+), 5 deletions(-) diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt index 59c1b02..a2f686c 100644 --- a/Documentation/git-rebase.txt +++ b/Documentation/git-rebase.txt @@ -257,11 +257,10 @@ include::merge-strategies.txt[] NOTES ----- -When you rebase a branch, you are changing its history in a way that -will cause problems for anyone who already has a copy of the branch -in their repository and tries to pull updates from you. You should -understand the implications of using 'git-rebase' on a repository that -you share. + +You should understand the implications of using 'git-rebase' on a +repository that you share. See also RECOVERING FROM UPSTREAM REBASE +below. When the git-rebase command is run, it will first execute a "pre-rebase" hook if one exists. You can use this hook to do sanity checks and @@ -396,6 +395,126 @@ consistent (they compile, pass the testsuite, etc.) you should use after each commit, test, and amend the commit if fixes are necessary. +RECOVERING FROM UPSTREAM REBASE +------------------------------- + +Rebasing (or any other form of rewriting) a branch that others have +based work on is a bad idea: anyone downstream of it is forced to +manually fix their history. This section explains how to do the fix +from the downstream's point of view. The real fix, however, would be +to avoid rebasing the upstream in the first place. + +To illustrate, suppose you are in a situation where someone develops a +'subsystem' branch, and you are working on a 'topic' that is dependent +on this 'subsystem'. You might end up with a history like the +following: + +------------ + o---o---o---o---o---o---o---o---o master + \ + o---o---o---o---o subsystem + \ + *---*---* topic +------------ + +If 'subsystem' is rebased against 'master', the following happens: + +------------ + o---o---o---o---o---o---o---o master + \ \ + o---o---o---o---o o'--o'--o'--o'--o' subsystem + \ + *---*---* topic +------------ + +If you now continue development as usual, and eventually merge 'topic' +to 'subsystem', the commits will remain duplicated forever: + +------------ + o---o---o---o---o---o---o---o master + \ \ + o---o---o---o---o o'--o'--o'--o'--o'--M subsystem + \ / + *---*---*-..........-*--* topic +------------ + +Such duplicates are generally frowned upon because they clutter up +history, making it harder to follow. To clean things up, you need to +transplant the commits on 'topic' to the new 'subsystem' tip, i.e., +rebase 'topic'. This becomes a ripple effect: anyone downstream from +'topic' is forced to rebase too, and so on! + +There are two kinds of fixes, discussed in the following subsections: + +Easy case: The changes are literally the same.:: + + This happens if the 'subsystem' rebase was a simple rebase and + had no conflicts. + +Hard case: The changes are not the same.:: + + This happens if the 'subsystem' rebase had conflicts, or used + `\--interactive` to omit, edit, or squash commits; or if the + upstream used one of `commit \--amend`, `reset`, or + `filter-branch`. + + +The easy case +~~~~~~~~~~~~~ + +Only works if the changes (patch IDs based on the diff contents) on +'subsystem' are literally the same before and after the rebase. + +In that case, the fix is easy because 'git-rebase' knows to skip +changes that are already present in the new upstream. So if you say +(assuming you're on 'topic') +------------ + git rebase subsystem +------------ +you will end up with the fixed history +------------ + o---o---o---o---o---o---o---o master + \ + o'--o'--o'--o'--o' subsystem + \ + *---*---* topic +------------ + + +The hard case +~~~~~~~~~~~~~ + +Things get more complicated if the 'subsystem' changes do not exactly +correspond to the pre-rebase ones. + +NOTE: While an "easy case recovery" sometimes appears to be successful + even in the hard case, it may have unintended consequences. For + example, a commit that was removed via `git rebase + \--interactive` will be **resurrected**! + +The idea is to manually tell 'git-rebase' "where the old 'subsystem' +ended and your 'topic' began", that is, what the old merge-base +between them was. You will have to find a way to name the last commit +of the old 'subsystem', for example: + +* With the 'subsystem' reflog: after 'git-fetch', the old tip of + 'subsystem' is at `subsystem@\{1}`. Subsequent fetches will + increase the number. (See linkgit:git-reflog[1].) + +* Relative to the tip of 'topic': knowing that your 'topic' has three + commits, the old tip of 'subsystem' must be `topic~3`. + +You can then transplant the old `subsystem..topic` to the new tip by +saying (for the reflog case, and assuming you are on 'topic' already): +------------ + git rebase --onto subsystem subsystem@{1} +------------ + +The ripple effect of a "hard case" recovery is especially bad: +'everyone' downstream from 'topic' will now have to perform a "hard +case" recovery too! + + Authors ------ Written by Junio C Hamano <gitster@pobox.com> and -- 1.6.0.2.408.g3709 ^ permalink raw reply related [flat|nested] 29+ messages in thread
* [PATCH 2/3] Documentation: Refer to git-rebase(1) to warn against rewriting 2008-09-13 16:11 ` [PATCH 1/3] Documentation: new upstream rebase recovery section in git-rebase Thomas Rast @ 2008-09-13 16:11 ` Thomas Rast 2008-09-13 16:11 ` [PATCH 3/3] Documentation: add manpage about workflows Thomas Rast 0 siblings, 1 reply; 29+ messages in thread From: Thomas Rast @ 2008-09-13 16:11 UTC (permalink / raw) To: git; +Cc: Junio C Hamano This points readers at the "Recovering from upstream rebase" warning in git-rebase(1) when we talk about rewriting published history in the 'reset', 'commit --amend', and 'filter-branch' documentation. Signed-off-by: Thomas Rast <trast@student.ethz.ch> --- Documentation/git-commit.txt | 4 ++++ Documentation/git-filter-branch.txt | 4 +++- Documentation/git-reset.txt | 4 +++- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/Documentation/git-commit.txt b/Documentation/git-commit.txt index eb05b0f..eeba58d 100644 --- a/Documentation/git-commit.txt +++ b/Documentation/git-commit.txt @@ -144,6 +144,10 @@ It is a rough equivalent for: ------ but can be used to amend a merge commit. -- ++ +You should understand the implications of rewriting history if you +amend a commit that has already been published. (See the "RECOVERING +FROM UPSTREAM REBASE" section in linkgit:git-rebase[1].) -i:: --include:: diff --git a/Documentation/git-filter-branch.txt b/Documentation/git-filter-branch.txt index b0e710d..fed6de6 100644 --- a/Documentation/git-filter-branch.txt +++ b/Documentation/git-filter-branch.txt @@ -36,7 +36,9 @@ the objects and will not converge with the original branch. You will not be able to easily push and distribute the rewritten branch on top of the original branch. Please do not use this command if you do not know the full implications, and avoid using it anyway, if a simple single commit -would suffice to fix your problem. +would suffice to fix your problem. (See the "RECOVERING FROM UPSTREAM +REBASE" section in linkgit:git-rebase[1] for further information about +rewriting published history.) Always verify that the rewritten version is correct: The original refs, if different from the rewritten ones, will be stored in the namespace diff --git a/Documentation/git-reset.txt b/Documentation/git-reset.txt index 6abaeac..52aab5e 100644 --- a/Documentation/git-reset.txt +++ b/Documentation/git-reset.txt @@ -82,7 +82,9 @@ $ git reset --hard HEAD~3 <1> + <1> The last three commits (HEAD, HEAD^, and HEAD~2) were bad and you do not want to ever see them again. Do *not* do this if -you have already given these commits to somebody else. +you have already given these commits to somebody else. (See the +"RECOVERING FROM UPSTREAM REBASE" section in linkgit:git-rebase[1] for +the implications of doing so.) Undo a commit, making it a topic branch:: + -- 1.6.0.2.408.g3709 ^ permalink raw reply related [flat|nested] 29+ messages in thread
* [PATCH 3/3] Documentation: add manpage about workflows 2008-09-13 16:11 ` [PATCH 2/3] Documentation: Refer to git-rebase(1) to warn against rewriting Thomas Rast @ 2008-09-13 16:11 ` Thomas Rast 2008-09-13 16:11 ` Interdiff: [3/3] " Thomas Rast 0 siblings, 1 reply; 29+ messages in thread From: Thomas Rast @ 2008-09-13 16:11 UTC (permalink / raw) To: git; +Cc: Junio C Hamano This attempts to make a manpage about workflows that is both handy to point people at it and as a beginner's introduction. Signed-off-by: Thomas Rast <trast@student.ethz.ch> --- Interdiff follows. The important change is that the format-patch recipe says to use send-email, hopefully keeping people from damaging their patches via cut&paste. Unfortunately I still don't know how to make the blocks look right in manpage format. Documentation/Makefile | 2 +- Documentation/gitworkflows.txt | 330 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 331 insertions(+), 1 deletions(-) create mode 100644 Documentation/gitworkflows.txt diff --git a/Documentation/Makefile b/Documentation/Makefile index ded0e40..e33ddcb 100644 --- a/Documentation/Makefile +++ b/Documentation/Makefile @@ -6,7 +6,7 @@ MAN5_TXT=gitattributes.txt gitignore.txt gitmodules.txt githooks.txt \ gitrepository-layout.txt MAN7_TXT=gitcli.txt gittutorial.txt gittutorial-2.txt \ gitcvs-migration.txt gitcore-tutorial.txt gitglossary.txt \ - gitdiffcore.txt + gitdiffcore.txt gitworkflows.txt MAN_TXT = $(MAN1_TXT) $(MAN5_TXT) $(MAN7_TXT) MAN_XML=$(patsubst %.txt,%.xml,$(MAN_TXT)) diff --git a/Documentation/gitworkflows.txt b/Documentation/gitworkflows.txt new file mode 100644 index 0000000..b4b43da --- /dev/null +++ b/Documentation/gitworkflows.txt @@ -0,0 +1,330 @@ +gitworkflows(7) +=============== + +NAME +---- +gitworkflows - An overview of recommended workflows with git + +SYNOPSIS +-------- +git * + + +DESCRIPTION +----------- + +This tutorial gives a brief overview of workflows recommended to +use, and collaborate with, Git. + +While the prose tries to motivate each of them, we formulate a set of +'rules' for quick reference. Do not always take them literally; you +should value good reasons higher than following a random manpage to +the letter. + + +SEPARATE CHANGES +---------------- + +As a general rule, you should try to split your changes into small +logical steps, and commit each of them. They should be consistent, +working independently of any later commits, pass the test suite, etc. + +To achieve this, try to commit your new work at least every couple +hours. You can always go back and edit the commits with `git rebase +--interactive` to further improve the history before you publish it. + + +MANAGING BRANCHES +----------------- + +In the following, we will assume there are 'developers', 'testers' and +'users'. Even if the "Testers" are actually an automated test suite +and all "Users" are developers themselves, try to think in these terms +as you follow a software change through its life cycle. + +Usually a change evolves in a few steps: + +* The developers implement a few iterations until it "seems to work". + +* The testers play with it, report bugs, test the fixes, eventually + clearing the change for stable releases. + +* As the users work with the new feature, they report bugs which will + have to be fixed. + +In the following sections we discuss some problems that arise from +such a "change flow", and how to solve them with Git. + +We consider a fictional project with (supported) stable branch +'maint', main testing/development branch 'master' and "bleeding edge" +branch 'next'. We collectively call these three branches 'main +branches'. + + +Merging upwards +~~~~~~~~~~~~~~~ + +Since Git is quite good at merges, one should try to use them to +propagate changes. For example, if a bug is fixed, you would want to +apply the corresponding fix to all main branches. + +A quick moment of thought reveals that you cannot do this by merging +"downwards" to older releases, since that would merge 'all' changes. +Hence the following: + +.Merge upwards +[caption="Rule: "] +===================================== +Always commit your fixes to the oldest supported branch that require +them. Then (periodically) merge the main branches upwards into each +other. +===================================== + +This gives a very controlled flow of fixes. If you notice that you +have applied a fix to e.g. 'master' that is also required in 'maint', +you will need to cherry-pick it (using linkgit:git-cherry-pick[1]) +downwards. This will happen a few times and is nothing to worry about +unless you do it all the time. + + +Topic branches +~~~~~~~~~~~~~~ + +Any nontrivial feature will require several patches to implement, and +may get extra bugfixes or improvements during its lifetime. If all +such commits were in one long linear history chain (e.g., if they were +all committed directly to 'master'), it becomes very hard to see how +they belong together. + +The key concept here is "topic branches". The name is pretty self +explanatory, with a minor caveat that comes from the "merge upwards" +rule above: + +.Topic branches +[caption="Rule: "] +===================================== +Make a side branch for every topic. Fork it off at the oldest main +branch that you will eventually want to merge it into. +===================================== + +Many things can then be done very naturally: + +* To get the feature/bugfix into a main branch, simply merge it. If + the topic has evolved further in the meantime, merge again. + +* If you find you need new features from an 'other' branch to continue + working on your topic, merge 'other' to 'topic'. (However, do not + do this "just habitually", see below.) + +* If you find you forked off the wrong branch and want to move it + "back in time", use linkgit:git-rebase[1]. + +Note that the last two points clash: a topic that has been merged +elsewhere should not be rebased. See the section on RECOVERING FROM +UPSTREAM REBASE in linkgit:git-rebase[1]. + +We should point out that "habitually" (regularly for no real reason) +merging a main branch into your topics -- and by extension, merging +anything upstream into anything downstream on a regular basis -- is +frowned upon: + +.Merge to downstream only at well-defined points +[caption="Rule: "] +===================================== +Do not merge to downstream except: + +* with a good reason (such as upstream API changes that affect you), or + +* at well-defined points such as when an upstream release has been tagged. +===================================== + +Otherwise, the many resulting small merges will greatly clutter up +history. Anyone who later investigates the history of a file will +have to find out whether that merge affected the topic in +development. Linus hates it. An upstream might even inadvertently be +merged into a "more stable" branch. And so on. + + +Integration branches +~~~~~~~~~~~~~~~~~~~~ + +If you followed the last paragraph, you will now have many small topic +branches, and occasionally wonder how they interact. Perhaps the +result of merging them does not even work? But on the other hand, we +want to avoid merging them anywhere "stable" because such merges +cannot easily be undone. + +The solution, of course, is to make a merge that we can undo: merge +into a throw-away branch. + +.Integration branches +[caption="Rule: "] +===================================== +To test the interaction of several topics, merge them into a +throw-away branch. +===================================== + +If you make it (very) clear that this branch is going to be deleted +right after the testing, you can even publish this branch, for example +to give the testers a chance to work with it, or other developers a +chance to see if their in-progress work will be compatible. + + +SHARING WORK +------------ + +After the last section, you should know how to manage topics. In +general, you will not be the only person working on the project, so +you will have to share your work. + +Roughly speaking, there are two important workflows. Their +distinguishing mark is whether they can be used to propagate merges. +Medium to large projects will typically employ some mixture of the +two: + +* "Upstream" in the most general sense 'pushes' changes to the + repositor(ies) holding the main history. Everyone can 'pull' from + there to stay up to date. + +* Frequent contributors, subsystem maintainers, etc. may use push/pull + to send their changes upstream. + +* The rest -- typically anyone more than one or two levels away from the + main maintainer -- send patches by mail. + +None of these boundaries are sharp, so find out what works best for +you. + + +Push/pull +~~~~~~~~~ + +There are three main tools that can be used for this: + +* linkgit:git-push[1] copies your branches to a remote repository, + usually to one that can be read by all involved parties; + +* linkgit:git-fetch[1] that copies remote branches to your repository; + and + +* linkgit:git-pull[1] that does fetch and merge in one go. + +Note the last point. Do 'not' use 'git-pull' unless you actually want +to merge the remote branch. + +Getting changes out is easy: + +.Push/pull: Publishing branches/topics +[caption="Recipe: "] +===================================== +`git push <remote> <branch>` and tell everyone where they can fetch +from. +===================================== + +You will still have to tell people by other means, such as mail. (Git +provides the linkgit:request-pull[1] to send preformatted pull +requests to upstream maintainers to simplify this task.) + +If you just want to get the newest copies of the main branches, +staying up to date is easy too: + +.Push/pull: Staying up to date +[caption="Recipe: "] +===================================== +Use `git fetch <remote>` or `git remote update` to stay up to date. +===================================== + +Then simply fork your topic branches from the stable remotes as +explained earlier. + +If you are a maintainer and would like to merge other people's topic +branches to the main branches, they will typically send a request to +do so by mail. Such a request might say + +------------------------------------- +Please pull from + git://some.server.somewhere/random/repo.git mytopic +------------------------------------- + +In that case, 'git-pull' can do the fetch and merge in one go, as +follows. + +.Push/pull: Merging remote topics +[caption="Recipe: "] +===================================== +`git pull <url> <branch>` +===================================== + +Occasionally, the maintainer may get merge conflicts when he tries to +pull changes from downstream. In this case, he can ask downstream to +do the merge and resolve the conflicts themselves (perhaps they will +know better how to resolve them). It is one of the rare cases where +downstream 'should' merge from upstream. + + +format-patch/am +~~~~~~~~~~~~~~~ + +If you are a contributor that sends changes upstream in the form of +emails, you should use topic branches as usual (see above). Then use +linkgit:git-format-patch[1] to generate the corresponding emails +(highly recommended over manually formatting them because it makes the +maintainer's life easier). + +.format-patch/am: Publishing branches/topics +[caption="Recipe: "] +===================================== +* `git format-patch -M upstream..topic` to turn them into preformatted + patch files +* `git send-email --to=<recipient> <patches>` +===================================== + +See the linkgit:git-format-patch[1] and linkgit:git-send-email[1] +manpages for further usage notes. Also you should be aware that the +maintainer may impose further restrictions, such as "Signed-off-by" +requirements. + +If the maintainer tells you that your patch no longer applies to the +current upstream, you will have to rebase your topic (you cannot use a +merge because you cannot format-patch merges): + +.format-patch/am: Keeping topics up to date +[caption="Recipe: "] +===================================== +`git rebase upstream` +===================================== + +You can then fix the conflicts during the rebase. Presumably you have +not published your topic other than by mail, so rebasing it is not a +problem. + +If you receive such a patch (as maintainer, or perhaps reader of the +mailing list it was sent to), save the mail to a file and use +'git-am': + +.format-patch/am: Publishing branches/topics +[caption="Recipe: "] +===================================== +`git am < patch` +===================================== + +One feature worth pointing out is the three-way merge, which can help +if you get conflicts because of renames: `git am -3` will use index +information contained in patches to reconstruct a merge base. See +linkgit:git-am[1] for other options. + + +SEE ALSO +-------- +linkgit:gittutorial[7], +linkgit:git-push[1], +linkgit:git-pull[1], +linkgit:git-merge[1], +linkgit:git-rebase[1], +linkgit:git-format-patch[1], +linkgit:git-send-email[1], +linkgit:git-am[1] + +GIT +--- +Part of the linkgit:git[1] suite. -- 1.6.0.2.408.g3709 ^ permalink raw reply related [flat|nested] 29+ messages in thread
* Interdiff: [3/3] Documentation: add manpage about workflows 2008-09-13 16:11 ` [PATCH 3/3] Documentation: add manpage about workflows Thomas Rast @ 2008-09-13 16:11 ` Thomas Rast 0 siblings, 0 replies; 29+ messages in thread From: Thomas Rast @ 2008-09-13 16:11 UTC (permalink / raw) To: git; +Cc: Junio C Hamano --- Documentation/gitworkflows.txt | 24 ++++++++++++++---------- 1 files changed, 14 insertions(+), 10 deletions(-) diff --git a/Documentation/gitworkflows.txt b/Documentation/gitworkflows.txt index 3462000..b4b43da 100644 --- a/Documentation/gitworkflows.txt +++ b/Documentation/gitworkflows.txt @@ -92,8 +92,8 @@ Topic branches Any nontrivial feature will require several patches to implement, and may get extra bugfixes or improvements during its lifetime. If all -such commits were in one long linear history chain (e.g. if they were -all committed directly to, 'master'), it becomes very hard to see how +such commits were in one long linear history chain (e.g., if they were +all committed directly to 'master'), it becomes very hard to see how they belong together. The key concept here is "topic branches". The name is pretty self @@ -124,8 +124,8 @@ elsewhere should not be rebased. See the section on RECOVERING FROM UPSTREAM REBASE in linkgit:git-rebase[1]. We should point out that "habitually" (regularly for no real reason) -merging a main branch into your topics--and by extension, merging -anything upstream into anything downstream on a regular basis--is +merging a main branch into your topics -- and by extension, merging +anything upstream into anything downstream on a regular basis -- is frowned upon: .Merge to downstream only at well-defined points @@ -207,7 +207,7 @@ There are three main tools that can be used for this: * linkgit:git-fetch[1] that copies remote branches to your repository; and -* linkgit:git-pull[1] that is fetch and merge in one go. +* linkgit:git-pull[1] that does fetch and merge in one go. Note the last point. Do 'not' use 'git-pull' unless you actually want to merge the remote branch. @@ -258,7 +258,7 @@ follows. Occasionally, the maintainer may get merge conflicts when he tries to pull changes from downstream. In this case, he can ask downstream to do the merge and resolve the conflicts themselves (perhaps they will -know better how to react). It is one of the rare cases where +know better how to resolve them). It is one of the rare cases where downstream 'should' merge from upstream. @@ -274,12 +274,15 @@ maintainer's life easier). .format-patch/am: Publishing branches/topics [caption="Recipe: "] ===================================== -`git format-patch -M upstream..topic` and send out the resulting files. +* `git format-patch -M upstream..topic` to turn them into preformatted + patch files +* `git send-email --to=<recipient> <patches>` ===================================== -See the linkgit:git-format-patch[1] manpage for further usage notes. -Also you should be aware that the maintainer may impose further -restrictions, such as "Signed-off-by" requirements. +See the linkgit:git-format-patch[1] and linkgit:git-send-email[1] +manpages for further usage notes. Also you should be aware that the +maintainer may impose further restrictions, such as "Signed-off-by" +requirements. If the maintainer tells you that your patch no longer applies to the current upstream, you will have to rebase your topic (you cannot use a @@ -319,6 +322,7 @@ linkgit:git-pull[1], linkgit:git-merge[1], linkgit:git-rebase[1], linkgit:git-format-patch[1], +linkgit:git-send-email[1], linkgit:git-am[1] GIT -- 1.6.0.2.408.g3709 ^ permalink raw reply related [flat|nested] 29+ messages in thread
* Re: [RFC PATCH] Documentation: new upstream rebase recovery section in git-rebase 2008-09-02 20:18 [RFC PATCH] Documentation: new upstream rebase recovery section in git-rebase Thomas Rast 2008-09-02 21:39 ` Junio C Hamano @ 2008-09-08 22:55 ` Junio C Hamano 2008-09-09 5:42 ` Thomas Rast 1 sibling, 1 reply; 29+ messages in thread From: Junio C Hamano @ 2008-09-08 22:55 UTC (permalink / raw) To: Thomas Rast; +Cc: git Any follow-up on this topic since: http://thread.gmane.org/gmane.comp.version-control.git/94701/focus=94761 ^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [RFC PATCH] Documentation: new upstream rebase recovery section in git-rebase 2008-09-08 22:55 ` [RFC PATCH] Documentation: new upstream rebase recovery section in git-rebase Junio C Hamano @ 2008-09-09 5:42 ` Thomas Rast 0 siblings, 0 replies; 29+ messages in thread From: Thomas Rast @ 2008-09-09 5:42 UTC (permalink / raw) To: Junio C Hamano; +Cc: git [-- Attachment #1: Type: text/plain, Size: 314 bytes --] Junio C Hamano wrote: > Any follow-up on this topic since: > > http://thread.gmane.org/gmane.comp.version-control.git/94701/focus=94761 I've been busy doing other work, sorry. I haven't forgotten though, and will definitely get back to it :-) - Thomas -- Thomas Rast trast@student.ethz.ch [-- Attachment #2: This is a digitally signed message part. --] [-- Type: application/pgp-signature, Size: 197 bytes --] ^ permalink raw reply [flat|nested] 29+ messages in thread
end of thread, other threads:[~2008-10-19 20:08 UTC | newest] Thread overview: 29+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2008-09-02 20:18 [RFC PATCH] Documentation: new upstream rebase recovery section in git-rebase Thomas Rast 2008-09-02 21:39 ` Junio C Hamano 2008-09-03 5:38 ` Thomas Rast 2008-09-11 15:38 ` [PATCH 0/2.5] " Thomas Rast 2008-09-11 15:38 ` [PATCH 1/2] " Thomas Rast 2008-09-11 15:38 ` [PATCH 2/2] Documentation: Refer to git-rebase(1) to warn against rewriting Thomas Rast 2008-09-11 15:39 ` [RFC PATCH] Documentation: add manpage about workflows Thomas Rast 2008-09-11 16:37 ` Jakub Narebski 2008-09-12 7:26 ` [RFH] Asciidoc non-example blocks [was: Re: [RFC PATCH] Documentation: add manpage about workflows] Thomas Rast 2008-09-20 0:22 ` [RFC PATCH] Documentation: add manpage about workflows Santi Béjar 2008-09-21 20:26 ` Dmitry Potapov 2008-09-30 16:05 ` Thomas Rast 2008-09-30 16:07 ` Thomas Rast 2008-10-01 9:54 ` Santi Béjar 2008-10-09 11:42 ` [RFC PATCH v2] " Thomas Rast 2008-10-09 11:42 ` [Interdiff] " Thomas Rast 2008-10-09 12:50 ` Junio C Hamano 2008-10-19 15:20 ` [RFC PATCH v3] " Thomas Rast 2008-10-19 15:20 ` [Interdiff] " Thomas Rast 2008-10-19 20:07 ` Junio C Hamano 2008-09-12 1:15 ` [PATCH 1/2] Documentation: new upstream rebase recovery section in git-rebase Marcus Griep 2008-09-13 5:08 ` Junio C Hamano 2008-09-13 16:10 ` [PATCH 0/3] Documentation: rebase and workflows Thomas Rast 2008-09-13 16:11 ` [PATCH 1/3] Documentation: new upstream rebase recovery section in git-rebase Thomas Rast 2008-09-13 16:11 ` [PATCH 2/3] Documentation: Refer to git-rebase(1) to warn against rewriting Thomas Rast 2008-09-13 16:11 ` [PATCH 3/3] Documentation: add manpage about workflows Thomas Rast 2008-09-13 16:11 ` Interdiff: [3/3] " Thomas Rast 2008-09-08 22:55 ` [RFC PATCH] Documentation: new upstream rebase recovery section in git-rebase Junio C Hamano 2008-09-09 5:42 ` Thomas Rast
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).