El 18/4/2008, a las 11:44, "Pat Maddox" <[EMAIL PROTECTED]> escribió:
> I believe that pull-merge-commit would work fine, I experimented > locally to understand the effects of handling submodule reference > merge conflicts. As I mentioned before, it is just a bit of a hassle > to have to do. David also pointed out that even without the > conflicts, you still have to commit the reference, leading to lots of > "updated rspec-rails" type commits in rspec-dev. Yes, it sounds like the whole submodule approach was a poor match for RSpec's organizational structure. I think submodules are really intended for super-projects which aggregate other _independent_ projects for easy consumption by others. Note that the emphasis is on _consumption_. So as you've discovered, while cloning rspec-dev.git and getting all the submodules is nice, it's not so convenient when it comes to actually contributing back. Submodules are really optimized for situations where Project A includes Projects X, Y and Z as submodules, the developers of X, Y and Z mostly work _within_ those projects, and the super-project is only occasionally updated. When I started using Git the whole submodule thing wasn't exposed yet, so it wasn't something I had to consider, but it was already a problem I'd faced previously when I experimented with using SVK as a layer on top of SVN (I was just too sick of SVN's lack of merge tracking). SVK doesn't have svn:externals support, either, you see. I ended up going for the simplest possible solution: symlinks (you can't nest one SVK checkout within another so I really did need to keep them in separate locations). And when I moved to Git I just continued on with the same arrangement, which has worked fine. Although your end solution differs in the details (a rake task which effectively does a few nested clones), the end result is not all that different. The key point is that rspec-dev.git is not actually a "product" intended for consumption by anyone other than people actually working on RSpec itself. It's just a convenience for grouping together a bunch of other projects (which really _must_ belong in repositories of their own because they are consumed by end-users independently of one another) and doing stuff like running a "pre_commit" task to make sure that everything is working. > pull-merge-commit is probably a good workflow (and indeed the only > one, because otherwise it's push-REJECTED-pull-merge-commit). Or fetch-then-rebase-then-commit pull by itself is actually fetch-then-merge If you rebase often (and you probably should in a project like this were there are multiple contributors) then you can do "pull --rebase" as a shortcut for fetch-then-rebase with a recent-enough version of Git. Pat, did you get that email I sent you off-list with the more detailed explanation of rebase? Pasting it in below as it may be of use to others. Cheers, Wincent El 10/4/2008, a las 8:52, "Pat Maddox" <[EMAIL PROTECTED]> escribió: > > Thanks for that. I wrote what's up on the wiki... and to be perfectly > honest, I only care about the end goal of having clean histories to > merge into RSpec core. I also don't fully understand everything you > wrote. If you had some time, perhaps you could take the existing > content, add some concrete examples of your techniques, and extract > all of that to a new page. I would certainly be very grateful :) I don't have a github account at this stage but here folllows a write- up that you could use to start a new page. Cheers, Wincent Using topic branches when contributing patches A "topic" branch is a separate branch that you use when working on a single "topic" (a bug fix, a new feature, or an experimental idea). Working on a topic branch instead of directly on top of "master" is recommended because: - it allows you to work on multiple, separate topics simultaneously without having them all jumbled together in a single branch - topic branches are easily updated, which means that if the remote "master" evolves while you are working on your topic it is easy to incorporate those changes into your local topic branch before submitting (which in turn will make your topic apply cleanly on top of the current "master") - if you receive feedback on your patches, having all the related changes grouped together in a topic makes it easy to tweak them and resubmit - working on a topic branch makes it easy to refactor a patch series into a logical, clear, clean sequence, which in turn makes your contribution easier to review and more likely to be included So, for all of these reasons it's recommended to use a topic branch for preparing submissions even for simple contributions like single- commit bugfixes and the like. Basic topic branch workflow Let's assume you are working in a clone of the official repository. If you set this up using a standard "git clone" then your local "master" branch will be set up to track the remote "master" branch automatically. # make sure that you're on your local "master" branch git checkout master # integrate latest changes from upstream git pull # create and switch to new topic branch named "my_topic" # (obviously you'd pick a more descriptive name) git checkout -b my_topic # now work on your submission, committing along the way ... # when ready, make a patch series for attachment to a lighthouse ticket git format-patch master That last command will create a numbered series of patch files, one for each commit on your topic branch (ie. all the commits since you branched off from "master"). Advanced topic branch workflow If your topic is long-lived then you can use "git rebase" to keep it up to date and massage it into shape. Imagine that the remote master has three commits at the time you start working: A--B--C You make a topic branch with three new commits: A--B--C \ X--Y--Z Meanwhile, the remote "master" continues to evolve and has three commits of its own: A--B--C--D--E--F \ X--Y--Z Without "git rebase", the only way to get your changes into the "master" branch is for the integrator to perform a merge, creating a new merge commit, M: A--B--C--D--E--F--M \ / X--Y--Z- With "git rebase" your changes can be "rebased" on top of the current remote "master". Git actually removes your three commits (X, Y and Z), "fast forwards" your topic branch to incorporate the latest commits from upstream (D, E and F) and then replays your commits on top of the new HEAD. A--B--C--D--E--F \ X'--Y'--Z' In this way when you submit your patches they can be applied using a simple "fast forward" merge which yields a nice, linear history: A--B--C--D--E--F--X'--Y'--Z' The content of the commits is the same but I've used the X', Y', Z' notation to indicate that the SHA-1 hashes for them will be different (because any change in their ancestry will bubble up and change their identifying hashes). There is no merge, so your patches are guaranteed to apply without merge conflicts. If there are any merge conflicts you will have already resolved them when you ran "git rebase". (This appropriately shifts the burden of resolving merge conflicts away from the central integrator onto the contributor; in this way the project can scale to have many contributors without the integrator becoming a bottleneck.) To make use of all this, all you have to do is: # integrate the latest upstream changes into your "master" git checkout master git pull # make sure that you're on your topic branch git checkout my_topic # do the rebase git rebase master "git rebase" can do more than just keep your topic branch up-to-date. Given our example commits X, Y and Z you might want clean up the history to make it easier to review (because the easier to review, the more likely it is to be accepted, you'll receive better feedback, and bugs are more likely to be caught). By running "git rebase -- interactive" you can: - remove a commit from a series (you realize that commit "Y" doesn't really belong in the series) - amend a commit (you realize that the commit message for "X" isn't quite right) - insert a commit into the series (you realize that you actually need a "W" commit before "X") - "squash" several commits into one (you realize that "X" and "Y" just make the same change in two different files, and so they logically belong in a single commit) - re-order commits (you realize that the series will be easier to understand if "Z" comes before "X" and "Y") When you run "git rebase --interactive" you'll see an editor window that allows you to perform all of the above operations in a simple fashion; you are presented with a list of commits which you can transform as follows: - delete a line to drop that commit - use "pick" (the default) for commits which you want to appear in the rebased history - change "pick" to "edit" for each commit you wish to amend (or perform additional commits) along the way - change "pick" to "squash" for each commit which you want melded into the previous commit - reorder the lines to reorder the commits The rebase will stop automatically for all commits you've marked as "edit", and will provide you with an opportunity to edit the commit message for commits melded together with "squash". It will also stop if there are any merge conflicts to resolve. When you are ready to resume the rebase you just do: git rebase --continue _______________________________________________ rspec-users mailing list rspec-users@rubyforge.org http://rubyforge.org/mailman/listinfo/rspec-users