What is the downside to managing a repository with multiple heads? - version-control

I have a project with a single branch, default. I have been iterating on this single named branch for some time now and I have been using tags to mark version number milestones.
The project's source code changed quite a bit between tags 1.0.7 and 1.1.0 (current). However, there are some users on 1.0.7 that need a bug fix. So I checked out the source, updated to tag 1.0.7, implemented a fix and committed. That was tagged 1.0.8, and will probably be the last commit on the 1.0.x line.
I now have two heads on the default branch. I expected that. But when I tried to push to our BitBucket account, I received a warning from hg: "push creates new remote head". Reading up on this message, I get a lot of answers explaining why the message is there and for most people the answer is just to merge. However, I don't think I want that in this case. The two branches aren't compatible.
It looks like I can just use the -f option to force push the new head to the remote repository, however this seems to be discouraged both by hg help and various posts on the web without much explanation as to why. So what is the downside to doing this? It seems as though I can still update to whatever tags/revisions I want to continue working on. If I push that head to the BitBucket account, will I be shooting myself in the foot in some way?

Having multiple heads is perfectly fine.
If there are several heads and there's little indication as to their purpose, it may be difficult for others to see where they should continue and what is the head which contains the newest developments, e.g. which gains new features.
However by using the tags on the branch with clear versioning like you do, that problem doesn't exist either.
There's one small catch though: Mercurial will, upon clone, update to the newest commit in the default branch - e.g. the head which received the last commit. If that's the 1.0.x head of yours, that might be unfortunate. However you can fix this, by attaching the special '#' bookmark to the mainline or development head. Mercurial will always update to the head which bears that bookmark, if it is present - irrespective which head has the newest commit.

Related

How to make update on GitHub?

I am studying how to use GitHub to collaborate with other people.
I have already set up Collaborators for one of my project and they have been able to download it.
But I don't know how to go for the next step. In other words, after they make their contribution; how are they supposed to upoad the result of their work, so that I can get it?
Yes indeed, by following the guides I have been able to make an update to a test project.
But everything is not quite clear yet.
I follow the process of creating-a-branch -> editing-something -> creating-a-pull-request -> merging-the-branch.
Then I delete the branch since it is no more needed. Apparently it works, but I can still see the deleted branch after, so it doesn't seem to be really deleted.
Starting July 2019, using GitHub Desktop, as part of its epic "branch pruning" and its 2.1.0 release, will prune those remote tracking branches for you.
Branches that have been merged and deleted on GitHub.com will now be pruned after two weeks.
See desktop/desktop issue 750:
We decided in taking a very conservative posture that we would only delete branches that aren't actively in use (hence the 14 days requirement) and don't have anything on them that's ahead of the default branch on GitHub. This combination, in addition to the branch being deleted on GitHub.com, seems relatively uncontroversial, but we're definitely going to listen to feedback we receive in the weeks and months after this ships to make sure it aligns with people's expectations and isn't overly aggressive.
Because we've taken an extremely conservative approach here, we don't intend to provide the ability to toggle it as a setting.
If you use a particularly branch frequently, this will never prune that branch, and it's restricted only to branches where there is no additional work that hasn't been merged into the default branch on GitHub.
In other words, we set this up intentionally such that users should never lose any work, which is our primary concern when deleting things. Hope that makes sense, and appreciate the feedback.

Proper push to modified remote repository workflow with egit

I am trying to jump over my shadow and finally learn git at a basic level. Like countless beginners before me I ran into the dreaded "egit rejected non-fast-forward" error when trying to push after merging in the remote changes and "marking as merged".
It seems like I already found a solution for this problem, but it is cumbersome and not compatible with the eclipse compare editor. I do it like this:
Push my changes - causes the "egit rejected non-fast-forward" error
Pull changes - The compare editor now contains <, = and > markers. I can't comfortably compare and push around changes as the right side of the compare editor is empty and the left contains my changes and the remote conflicting changes above each other, which is pretty useless.
Painfully pick the parts I want by manually editing the text.
Am I using egit the right way?
Is there a way to properly use both sides of the compare editor?
I want to see my version which will be pushed and it's differences to the current remote version at all times during the merge.
I'm not familiar with egit, but it sounds like you are dealing with a merge conflict. Am I right in assuming that someone else also has push access to the branch you're working on? What likely happened is they pushed new changes to the branch, which is what is causing the rejection. And by pulling, you're trying to merge in some conflicting changes that you have to resolve. Here is a better explanation of the same problem.
The bad news is that merge conflicts always have to be resolved manually. The good news is that it looks like egit provides a merge tool for resolving these conflicts. This egit wiki page might help you find the comparison tool that you're looking for. Basically, just select the file that has conflicts and then select Team > Merge Tool
.
If that doesn't work, you can always confidently resolve merge conflicts just by using the git merge markers (<, >, and =). Read this for a detailed explanation of how those are used in Git. Basically, anything below <<< and above === will be your changes. The code below === and above >>> will be their changes. And you either have to pick which side you want, or you can customize it even further. by deleting everything and re-writing the code yourself.
Here's an example. This is something you might see when resolving a merge conflict. The top show you the commit at your local HEAD, your version of the commit. And the bottom, below the === shows the commit at origin/master, the version you just pulled in.
<<<<<< HEAD:test.html
<h1>This is my version</h1>
======
This is their version
>>>>>> origin/master:test.html
To keep only your version, you could just replace that entire block with this. It's like the arrows and equal signs are giving you a choice. Do you want the top (yours), or the bottom (theirs)?
<h1>This is my version</h1>
Alternatively, maybe you want a combination of both. Here, you would be keeping your <h1> html tag, but using their text.
<h1>This is their version</h1>
I hope this helps you feel more comfortable with resolving merge conflicts. If you want to learn more about Git, I always recommend git-scm.

Mercurial-like named branches experience in Perforce

I am new to Perforce and find it really hard to follow its workflow..
I have used Mercurial before (not in any advanced ways), but what I lack most in Perforce is the idea of named branches.
Let me explain what I'd like to do:
I get the latest revisions of all files and want to work on a new feature/story/task..
I create a brach, say "Feature 3021"
I code, save changes in this branch (hg commit)
I can save changes to a central server (hg push)
When I'm done coding, I merge the changes from "Feature 3021" with the main branch (default, master, etc.) - after that the main branch has the code I wrote
I can close the named brach ("Feature 3021") so that further commits are not possible.
I don't need this exact behavior in Perforce, but something analogous. I know that Perforce is centralized, so the commit-push step would be probably one, but this is a minor problem here.
All I care is to be able to save my work in version control at any time, even if it's not 100% ready - perhaps to a different branch. I'd also like other users to be able to be able to get my code (from this different branch), but only if they want this - the default branch should stay unafected as long as I don't merge my changes with it.
Is it possible? I am using Server 2012.2
Can you upgrade to Server 2013.1 or later? There's a great feature there, called Task Streams.
Here's some references:
http://www.perforce.com/blog/130627/task-streams-even-if-you-are-classic-perforce-shop
http://www.perforce.com/blog/130206/task-streams
http://www.perforce.com/perforce/doc.current/manuals/p4v/streams_task.html
The analogous flow in Perforce would be:
Maintain a main-line "branch" at some path, say //depot/default
To create a feature branch, integrate from //depot/default to //depot/feature-3021
Work under //depot/feature-3021 and submit
When you are ready to merge back, integrate //depot/feature-3021 to //depot/default
Regarding closing the branch after its use, there are a couple of options that I can think of. You could either change permissions or simply delete it. The delete could always be recovered.
Also note the paths don't need to be at the same hierarchy. A more reasonable branch strategy might use paths like this.
Main-line: //depot/default
Developer branches: //depot/dev/${user}/${feature}

How to merge code changes using subclipse?

I'm using svn for the first time, to maintain a custom version of Wordpress. I'm using the subclipse plugin in eclipse. The time has come to merge the changes in the latest release of Wordpress with my customised code base.
I have tried creating a branch and adding the new Wordpress release there, then performing a merge. No changes were made however.
Could someone walk me through the setup of project like this? I fear I am missing something basic.
Thanks.
This is assuming you merge from branch (containing the latest version of Wordpress) to trunk (your customized codebase).
(Make sure that you have committed everything you need into branch.)
Team --> Switch to another branch/tag/revision... your working copy to trunk (the target of your merge operation), and resolve any conflicts that come up at this point.
Team --> Merge opens a dialog where you will be performing the merge operation. Change the "From" URL to reference branch (the source of your merge operation, i.e. what you want to merge into your working copy). "From Revision" should point to the revision in branch where you want your merge operation to "start" from - typically the revision that was last merged in from branch to trunk (or most likely the head revision in your case, if you really want to merge just that latest changes in branch).
Set "To Revision" to point to the latest revision in branch (= the head revision).
At this point you are ready to perform the merge - Dry run command lets you preview what will happen during the merge, and Merge will perform the actual merge.
Once the merge operation has been completed, you need to make sure that all changes that were performed against your working copy are ok, and resolve all conflicts.
When you're done with resolving conflicts and reviewing the changes, commit the changes to trunk in a single commit operation. For your own convenience, it is strongly recommended that you add a commit message where you specifically state what this commit is for ( = merging revisions from X to Y from branch to trunk, what was the purpose, etc.).
Hope this helps.
Converting wordpress project to vendor branch procedure
If you are using svn for the first time I suppose you have not started with a clean wordpress copy, branched from there and edited the branched version, have you? ;)
If that is so you might have a problem at your hands.
Background
Unlike "regular diffs" SVN merge does not compare right-side code/folders with left-side code/folders.
While svn merge might fall back to a diff-like mechanism if it does not find a history, I would not recommend relying on that as it can be quite prone to unneccessary conflicts.
SVN Merge is used to reproduce changes that have been recorded in the SVN history. It is like telling a painter "Hey you know how this picture looked before you added that tree on the hill? That Tree was great! Look here i've copied the same base picture but now it's with a sunset. Can you paint the same tree again but on this picture with the sunset?"
The painter might be able to reproduce the tree because he knows how he had done it. He might even have a draft somewhere.
The picture, that is wordpress. The painter, its svn with you commanding it. The tree thats your modifications. The picture now sunset-themed is the newer wordpress version.
What most likely you did is copy wordpress vanilla into your svn, modify it, work with it.
To stick with the picture example, the history would contain commands like "copy whole picture, add tree, add leaves".
Now you bring a new version of wordpress, a new picture so to say and put it besides your older modified version. The Problem is, you human and smart know its quite much the same picture and even though the newer verison is different you just have to copy the tree, SVN does not have that knowledge. For SVN your wordpress 1.7 folder (modified) is completly distinct from wordpress 1.8. They share no history because nothing in SVNs log indicate it. SVN is a bureaucratic snob isn't it? ;)
Now what people do to allow svn to maintain that historic connection between wordpress 1.7, your modified 1.7 and the new 1.8 is they use branching right at the beginning of their works.
So you would start off with a clean 1.7 wordpress in a "vanilla-wordpress" folder, store it in svn and branch it to, say, "my-modified-wp". There you hack away until you feel like updating wordpress from upstream. People then download the latest wordpress copy overwrite their vanilla wordpress and merge the resulting changeset.
In the picture example commands would be these:
"Buy original picture
copy original picture as my picture
draw tree on my picture
draw sunset on original picture (someone else did that for you, aka update)
*reproduce* sunset on my picture too"
You can cleanly reproduce the sunset because you know how the picture looked before the sunset was applied.
Your problem though is that you did not start that way off but edited on your downloaded wordpress right away. So your newer copy of wordpress can not be easily associated with your modified version.
One way to establish history relations
download the **exact** wordpress version you started your project with
Put it into /vendor/wordpress/current
invoke "svn copy http://svnserver.tld/repositorypath/vendor/wordpress/current http://svnserver.tld/repositorypath/vendor/wordpress/1.7.1" to tag the import.
invoke "svn copy http://svnserver.tld/repositorypath/vendor/wordpress/current http://svnserver.tld/repositorypath/branches/my-new-modified-wordpress" or whatever your project/WP-edition is called.
Now comes the trick part
Scroll back the svn log of your "old-modified-wordpress". The one that you did not branch. You have to find the first revision AFTER your initial import of the old wordpress. Once you found that revision you take its number and use it in the second of these two commands:
change into a local checkout of "/branches/my-new-modified-wordpress"
issue "svn merge -r **4**:HEAD http://svnserver.tld/repositorypath/my-**old**-modified-wordpress". If 4 was the first revision during which you made own modifications.
You are telling svn the following: "Take all changes in my old branch between revision 4 and NOW and reproduce them on my new branch."
If all works out you should have two identical branches. the old-modified and the new-modified with the slight difference that the new-modified has a solid history with your "/vendor/wordpress/current" branch.
This ancestry allows you to contunously do the following:
Download the wordpress version you wish to upgrade too and **overwrite** /vendor/wordpress/current
invoke "svn copy http://svnserver.tld/repositorypath/vendor/wordpress/current http://svnserver.tld/repositorypath/vendor/wordpress/1.9.3" to tag the new version.
change into local checkout /branches/my-new-modified-wordpress
issue "svn merge http://svnserver.tld/repositorypath/vendor/wordpress/current"
profit
This procedure I describe with less storystelling at the link allready. But before it can work you have to establish the ancestry relation between the branches.
Subversion svn:externals file override?
I know it has been alot to read :). If you plan do soem drawing, think of "change commands" not states and you'll be fine.
C

Proper usage of Tags in SCM

My co-workers and I are having an argument over the value and usage of Tags in release/SCM systems. We're looking to the StackOverflow community to put in their thoughts to help us resolve the issue.
One side claims that Tags are a valuable addition to release management. An example of their use: we do a Maven release, which makes a new Tag (call it 1.0) which is code snapshot used for this release. This Tag should be a READONLY branch. When a bug needs to be fixed we can make a copy of the Tag into a new Branch (call it 1.1). Bug fixes go there. These fixes may be merged back into Trunk so that the main dev branch gets the bug fixes. Finally, 1.1 is released and a Tag 1.1 is automatically created. This cycle continues. The main benefit here of the Tag is that if you ever need to re-release version 1.0 for any reason, you can just release the Tag 1.0 with the confidence that it's never been altered by anyone. Also, saying "Release Tag 1.0" is cleaner than saying "Release revision 1 of branch 1.0 which is the original 1.0 without the fixes".
The other side claims that Tags aren't providing any valuable benefit, especially in a system like Subversion with global revisions, which act like a Tag in CVS. Plus, Subversion only gives a warning when committing to a Tag; it doesn't actually stop it. Their method is developing in Trunk and upon release you'd make a Branch called 1.0. You'd continue bug fixes in Trunk and if you needed to re-release those bug fixes to production, you'd merge them into 1.0 Branch and re-release 1.0. At some point, perhaps after major fixes or features in Trunk, you'd release and make Branch 1.1. Cycle continues. If you ever need to release the original 1.0 version, you'd have to check out Branch 1.0 revision 1.
Clearly both methods work. I'd like to hear the community's thoughts on which method is preferred and why.
Edit: I'm a little worried that the "best" way depends on the underlying SCM system. Either settle on Subversion for answers or if possible keep it SCM agnostic.
From an SCM agnostic point of view, a tag is very different from a revision.
Both may be implemented in the same way, both represents a "time line", but their goal is different:
a tag represent an immutable state where all files are referenced by a unique id. It is a name representing many things but mainly a stable state, ...)
a revision represent a commit transaction (not all SCM have those, especially the old ones with a 'file-by-file approach'). All commits do not represent a "stable" state (as in "compile" or "execute" successfully). They are just a new element of the global history.
The problem with SVN is that revision, tag and branches are all implemented the same.
But I would still prefer the option where a tag is used as a "read-only" branch.
In my opinion tags are useful. There will be times at some point in the life of the project that you come across a bug or a change and you want to know if it was there in a previous release. There will be reasons to compare code from one release to another to measure efficiencies both in performance and actually the development of the code.
Sure, there is a chance you can screw it up, but it can always be undone. There really is no reason not to, and there are several reasons why it might be useful in the future. To me its a no-brainer.
I agree that you should also be using branches and doing your development there, but anytime you actually release something, make a tag out of it.
Yes, you want to use tags.
Think of a tag as just a label or a name for a particular revision. It is very helpful in my experience to tag important milestones in a project, whether it's for production release or even for interim QA releases. You often will want to go back in time and see the source code for a particular release.
If you branch upon release, you can always figure out which revision was released to production, but this is kind of a pain compared to just looking at a tag. If you don't use release branches then it will be easy to lose track of which revision was used to create a particular build.
The problem with svn is that it blurs the distinction between tags and branches. Anyone can always commit to a tag, so it's not guaranteed to be fixed/immutable. In other VCS like PVCS, a "tag" is unchangeable. You can adopt a team convention to prevent commits to tags, or even maybe use commit hooks to prevent commits to tags.
We use tags (labels) when creating new baselines. We do it once a week, but some teams do it even several times a day.
The point (for us) is always making sure the new baseline is stable: so it's not just a build, is a build that passes the entire testsuite, several hours of automated tests plus potentially manual exploratory ones too.
Then the baseline is used as starting point for all tasks during the next iteration: every new task is a new branch starting from the baseline, which is known to be stable so whatever is broken in the task should be easy to trace inside the task itself.
Normally we only put tags (labels) on the main branch (or trunk or master depending on your SCM flavour) which is the integration point for all the other branches.
When we release an official product we create a "release branch for it" so it will only receive fixes while new development stays on "main". Then these "maintenance branches" (hopefully only one or two at a time) can be tagged too.
I like to think about tags as "just a fancy name for a revision". I've always thought about them that way, and IIRC in mercurial they are just that. In subversion however, as you say, they indeed are (cheap) copies of trunk/* to tags/fancy-name/
Honestly, I'd combine the two strategies for optimal results: tag and branch upon release. Your tag is called 1.0.0, branch 1.0-MAINT. Bugfixes go into branches, and bugfix releases are tags again (1.0.1 may by a tag intended to alias 1.0-MAINT at a certain point.)
Do not forget however that tags and branches in subversion are actually the same thing: cheap copies. The only difference between them is the semantics you/your team attributes to them, so it pretty much boils down to getting people to agree on one particualr method and stick to that (might be enforced on the server, eg disallowing commits in tags/ except for release coordinators etc.)
The problem I see though with the second approach is: how are you going to make an easy distinction between software in the field if you re-release 1.0? That means that you may have a 1.0 and another 1.0 actually referring to a different code base... .
Immutable snapshots of a project's source code (and executable) are invaluable for doing testing of any kind, whether structured testing or field usage. For structured testing, you're going to be creating data that might be referenced months or years in the future. Anytime you revisit that data, Murphy's law says you'll need to know what code it comes from and unless you went to the trouble of citing a particular snapshot of the source code, it will be impossible to tell with confidence what source code corresponded to that test data.
I can't tell you how many times someone's come to me and said "This microcontroller code's not working, can you help?" and I ask them, "What version are you using?" and they say "I'm not sure" because they're not doing good release management (at the very least putting a sticker on the device, better to put versioning info in EEPROM that can be queried in realtime). >:(
In SVN, the technical difference between using a tag and tracking a revision is nil. I find myself minimizing tag use based on how SVN's implementation is simply a cheap copy and clutters up your "structure space".
The real difference comes when communicating a particular baseline to a large team of developers. Revision tracking brings an extra layer of abstraction that can become a source of errors. And as we're all aware, when you're dealing with 50+ developers, any source of error will become an area of confusion and wasted time. A verbose tag can eliminate that confusion and remove any doubt as to what a baseline's purpose is.
I'd combine both approaches. Whenever you make a release, tag it. Tags should never change, so the presence of a "1.0.0" tag is an indicator that you shouldn't be trying to release anything else as 1.0.0.
At the same time, when it came time to do 1.0.0, I'd put it onto a 1.0 branch. So the flow is: branch trunk to 1.0, tag this new 1.0 as 1.0.0, and deploy. Then bug fixes can be done on the 1.0 branch (to avoid getting mixed up with any 1.1-targetted development that may already be on trunk now) and merged into trunk. Each release of the fixed 1.0 is tagged as 1.0.x from the 1.0 branch. This is basically the approach we use at work with Perforce, and that's very similar indeed to Subversion. (Reading through the replies, I think it's virtually identical to Vincent's recommendation)
As far as the comment about tags being redundant because you have revision numbers--- that's largely true, except that tags also specify a scope: i.e. which files in the repository are covered by the tag. You can reasonably ask someone to look at /svn/proj1/tag/1.0.0 and they are immediately looking at a coherent workspace. If you ask them to look at revision X, they have to first look at revision X to see that it was changing (say) /svn/proj1/trunk/Makefile and hence deduce that /svn/proj1/trunk/#X is what they should be looking at. What happens if revision X touched files in proj1 and proj2? Which is of course evil, but strictly speaking you should be saying /svn/proj1/trunk/#X. And where is the list of revision numbers stored? How do we know that 1.0.0 is revision X? It should IMHO be possible to determine that just from the repository.
In systems like Git, tags and branches are still basically the same thing (just references to the object database), but the convention is that tag refs don't change, and branch refs do (and preferably with a specific constraint on how they change). Perforce also has "labels" which are ways of grouping a set of file revisions together independently of a changelist; which is essentially a tag, but more confusing: historically we've used changelist numbers (equivalent to Subversion revision numbers) qualified with the name of the branch they should be on to identify versions. The two are almost identical any way, so here I guess TMTOWTDI.