I typically work on small-sized projects that involve only 2-3 people working on the same codebase concurrently.
The usual routine for me is as follows:
Scour through bug reports, pick a bug by priority, and write the fix
Create a diff/patch (let's call it patch "alpha") of the changes to the codebase (ie: svn diff > ~/diff_alpha.patch)
E-mail the patch to colleagues where they can visually inspect the diff against the codebase and point out errors or suggestions
They tell me what changes are required, I put them in, and then re-email my team with the modified patch
Once everyone agrees that the patch is good, I apply it to the codebase, merging in other people's changes if necessary, re-build, re-test, and commit.
The problem here is that I usually have to wait a couple of days for all the approvals for the modified final patch to come in, and during that time I (obviously) want to work on other patches.
If I go work on another bug and it affects the same file I'm working on in the previous patch, it means that when I want to commit the previous patch (alpha), I have to:
Backup my current work to a new patch (ie: patch "bravo"), via svn diff > ~/diff_bravo.patch
Revert my current working copy (svn revert -R .)
Apply the old patch (patch -p0 < ~/diff_alpha.patch)
Commit the old patch (svn commit)
Apply the patch I was previously working on (patch -p0 < ~/diff_bravo.patch)
Continue working on the code related to diff_bravo.patch
This is annoying as I generally have to hand-merged conflicts between diff_alpha and diff_bravo.
The other approach I tried was just continuing my work on diff_alpha without creating a diff_bravo. Then, when I have approval for all the code in the original diff_alpha I e-mailed out, I do the following:
Backup my current work to a new patch (ie: patch "temp"), via svn diff > ~/diff_temp.patch
Revert my current working copy (svn revert -R .)
Apply the old patch (patch -p0 < ~/diff_alpha.patch)
Commit the old patch (svn commit)
Apply the patch I was previously working on (patch -p0 < ~/diff_temp.patch)
Now I can continue what I was doing without having to hand-merge, but I will receive tons of fails hunks in my "patch" command as half the code in diff_temp was already committed in diff_alpha. I do not find this acceptable.
Any recommendations for handling multiple tasks/bugs on a common file so I can minimize SVN conflicts?
This is what branches are for. You create a branch for each bug and work in that branch until you are ready to consult with your team mates. The branch can be checked out by the team members and inspected (update when you did new changes). When everyone agrees, merge branch back to trunk.
The team members can check the log of each change you made to the branch (essentially your patch in your question) or open the changed file and see the applied changes in context (they can even access previous version(s) of the files to see how it was before the change).
You still have to alert your team members to check the changes, but do not have to explicitly send them the change youself -- they will get it from the cental repository.
You can have multiple branches (one for each bug) and can work on them simultaneously. When merging to the trunk, SVN should do the merge automatically (occasionally pointing out conflicts, which you can resolve manually.
The conflicts might arise from the fact that the branch was created from an older version of the trunk and the current trunk state (containing some changes from other branches) is conflicting with the changes in your current branch. You manually resolve them as it makes sense. Re-test to make sure all is still well.
UPDATE: Based on Lazy Badger's comment, your team members can put commit monitors in place to alert them when you make a change to a (particular) branch.
When we work, we do most of our code reviews after the commit takes place. None of this patch files going back and forth. We use Jenkins and have plugins that can do lot of the checking for us (like Findbugs, PMD, CheckStyle, etc.). If we find issues, we can fix them in a new commit. If the change was bad, we can revert it.
If you like your current work flow, you might want to look at Git which allows you to share patches like this very easily between developers. It's one of the reasons why Git is so popular.
I also have a Commit Monitor plugin for Subversion (a post-commit hook really) that allows people to setup their own preferences on what changes they want to be notified on. The configuration is stored inside the repository, so users have access to it.
Related
I am using the Perforce P4V client (version 2013.1/611291, dated 2013 March 20).
I attempted to Merge/Integrate from the main branch to my feature branch. It had been a long time since I had done this, so a significant number of files were added to the changelist. I then resolved conflicting files that could not be merged automatically. I then submitted the changelist. After doing that, I discovered that some of the files had remained in a messy conflicting state. Exactly why is a mystery to me, but instead of trying to fix them, I thought it would be easier to just undo the Merge/Integrate entirely and start over again.
To undo the Merge/Integrate, I used the 'back out' option. All affected files were added to the 'back out' changelist and I submitted it. My feature branch is now back where it was to start with, except obviously by now all affected files have had their revision number bumped up twice, and the history for affected files shows the integration and then the subsequent 'back out'.
The problem is that if I try the Merge/Integrate option again, this time round the number of files that Perforce wants to put into the integration changelist is now a fraction of those it originally tried to integrate. Put another way, it's not adding lots of files that I know are most definitely further forward in terms of development in the main branch.
The only way I seem to be able to get around this is to use the advanced option Force integration on all revisions, disregarding revision history (-f). With this option set, it will then add for merge all files from the branch.
I suspect the problem is something to do with the fact that the files now have an integration marked in their history, and therefore Perforce is using that point as the base. The fact that the messed-up integration was 'backed out' doesn't make any difference to that.
I tried to do a rollback as well, but the same problem remains.
How can I solve this?
Edit
I have later realised that there is the following similar question:
How can I undo an Integration in Perforce, and still be able to redo it?
The files which you're trying to integrate from the main branch to your feature branch have an integration history after your first integration check-in.
When you backed out the changes, you got your feature branch's files to the state where it was before the integration, but new versions of the files were created for each of the file in that previous changelist.
The next integrate hence tries to bring in ONLY the difference in the integration path since last time.
As you've mentioned already, the only way out of this situation is to run a force integrate using the -i. You can still resolve the changes using p4 resolve -as ... and p4 resolve -am ... just like last time, and then hand resolve the remaining conflicts to perform the merge. Except that the history would show 2 extra versions of the files changed in the prior merge commit and the commit for backing it out.
If you're okay with creating a feature branch at a different location and discarding the one at your current location, you could set the starting point for the new feature branch to be the commit/changelist just before you performed the problematic integrate.
Integrate from your main branch into the new feature branch and you should have a much cleaner history this time and should have all the file changes (with history) you've made in your original feature branch as well.
Unlike other version control systems (like git for example), it is unfortunately not possible to rewrite history in perforce to make it forget about the integration history and start fresh again.
This is one of the reasons in my company, all the architects and SCMs are very much picky and reiterating their workflow advice, about strictly following integration paths between branches when performing integrations using perforce.
I've been using Tortoise SVN + Visual SVN for about a year since left the corporate world to do my own startup. There's one feature in Tortoise SVN that I've never figured out:
How can I bundle up a bunch of changes into a PATCH or DIFF file and either: A) share them with my co-founder; or B) archive them into a standalone change that I can either "apply" or "revert" on my dev box?
At my previous employer, we used an internal tool that let us build so-called DPK files that contained a set of local changes. You could add changed files to the DPK and then share it with colleagues. They could either review the changes in a Diff tool or apply all the changes from the DPK to test your change on their box. After the review was complete, you could then check in these changes. You could also have multiple DPK's applied at the same time (provided you didn't have overlapping changes).
I want to achieve the same thing with Tortoise SVN + Visual SVN in the VS2010 IDE.
My real-world scenario is that I have some extensive change pending but uncompleted on my box. I want to ZIP up these changes and store them in a DIFF file, revert the changes, move on to something else, work on that, and in a few days reapply my changes from the archived DIFF file.
Reluctantly answering my own question. This feature is available with Tortoise SVN. Basically, you make a PATCH file, distribute it or archive it, and then you apply the PATCH. The only trick is to make sure you're in the right location in the WC (Working Copy) when you do the "apply". When you apply, you'll get a popup menu to the left with a list of all files in the changelist. You can apply the patches one by one or in bulk. Seems to work great. I should have drilled into the docs more before posting this question.
Here's the text for picking the location:
"Patch files are applied to your
working copy. This should be done from
the same folder level as was used to
create the patch. If you are not sure
what this is, just look at the first
line of the patch file. For example,
if the first file being worked on was
doc/source/english/chapter1.xml and
the first line in the patch file is
Index: english/chapter1.xml then you
need to apply the patch to the
doc/source/ folder. However, provided
you are in the correct working copy,
if you pick the wrong folder level,
TortoiseSVN will notice and suggest
the correct level."
Be sure to pick the location carefully. If Tortoise SVN can't find it because you selected the wrong node in the VS file explorer, it will try to find a matching location and that might be wrong. In my tests, the Patch feature actually tried to map to a branch (!!) when I specified the wrong location.
Here's the relevant link:
http://tortoisesvn.net/docs/release/TortoiseSVN_en/tsvn-dug-patch.html
I'm using TortoiseSVN without an external Subversion server to manage LabView source (i.e. a large collection of ever-changing binary files).
I'd like to have a "beta" branch of the repository that anyone can subscribe to and get daily updates. I guess this is different from a usual beta release series with separate branches, but it's right for this project.
What is the best/easiest way to copy the contents of a particular revision of the trunk branch over to the beta branch? Essentially what I want to do is delete the old contents of beta and insert new contents. Delete+add would work, I suppose, but it's clearly suboptimal. Merge is not an option unless I can get Tortoise to automatically resolve all conflicts in the trunk's favor, including deleting files.
Update: a couple people have asked why I don't want delete+add. I'd like a cleaner alternative.
This method leads to half the updates to the beta tree being "wipe out last rev."
The updates are not atomic so someone could pick up an empty release.
I haven't tried and seen, but beta wouldn't be a proper branch. Would the revision log even track multiple revisions at all, since it's a "new" file each time?
Update 2: svn allows any arbitrary commands before a commit, but I couldn't get Tortoise to work this way. After selecting "Delete," stub directories were still left over until I committed, at which point I could repopulate the branch. There needs to be a way to unmark a directory for deletion when it exists in both the old and new tag revisions.
Merge is not an option unless I can
get Tortoise to automatically resolve
all conflicts in the trunk's favor,
including deleting files.
I don't know about TortoiseSVN, but if you install the command line client you could do the following to merge the latest trunk changes to a beta branch:
cd c:/path/to/my/working/copy/of/beta/branch
svn merge file:///c:/path/to/my/repository/trunk --accept theirs-full
svn commit -m "merged latest trunk changes to beta branch"
The --accept theirs-full option resolves all conflicts by using the trunk's version like you want.
This has some advantages: subversion will do representation sharing, so files stored on both branches will not take extra space in the repository. Also, when users update their beta working copy, only the files that were changed need to be pulled over the wire.
SVN is transactional - a delete and copy (not add!) would not be problematic. And beta would be a proper branch (or better a tag)
Why not delete beta/* and then copy trunk/* to beta/ ?
I wish to check my changes into a different branch than the files were check out from. All the files there are the same “version” in each branch, Perforce should know this from tracking the integrations that have been done. (So no merging need to be done)
According to the Perforce Blog, the p4 move -f command will move your edit from one branch to the other. From the blog
This can be a real lifesaver if (as I did a few weeks ago) you start working on a fix in your mainline, and then decide that it needs to go into your release branch instead. Previously you would have needed to save a copy of your work, revert it, open the files in the release branch, and copy your edits back in manually — now you just “p4 move -f main/… rel/…” and all your edits go where you need them.
This is a new feature added in version 2010.1 (this year I believe) so that's probably why tech support didn't know about it.
Use "p4 move" if you have version 2009.1 or later. Just move to the new branch and revert from the old branch.
I just got an answer from support#perforce.com
You cannot check files into a branch
that they weren't checked out from.
You need to open those other files for
edit and copy your changed files over.
(I am now beginning to understand why pressure is building up from some the programmer I work with to to move to Mercurial)
(I am a new perforce user, but have used lots of other source code control systems in the past.)
We use a change list to check-in each bug fix; the change list comment includes the bug ID therefore it is easy to track when a bug fix has been checked into a branch.
However I can’t see an easy way to find all branches a given bug fix has been merged into, or to find all bug fixes that have been merged into a given branch.
As far as I can tell perforce does not track all the branches a change list have been merged into. As I understand it, when a merge is done in perforce the history is not copied into the target branch so the only history in the target in the comment on the change list the merge was done into.
What am I missing?
Perforce tracks where revisions of a file have been integrated, but it doesn't automatically propagate check-in comments with your bug-tracking metadata.
Given a changelist on a particular branch, you can tell whether Perforce thinks the changelist has been integrated by asking Perforce to integrate the changelist. (I'm using "branch" in the more traditional source-control sense, to mean a particular branch of the source code tree, rather than in the specific Perforce sense to mean the path of integration between these two source code trees.) Let's say you've been working in //source/project/trunk/... and you have a changelist #1234 that you'd like to check whether it's been integrated into your release branch //source/project/rel/.... Create a client that maps //source/project/rel/... and execute:
$ p4 integrate -n //source/project/trunk/...#1234,1234 //source/project/rel/...
If Perforce tells you "All revision(s) already integrated.", changelist #1234 has been integrated, and that bugfix ought to be available on the release branch. If Perforce lists files that have changed, those files have not been integrated. (It's also possible for some files in a changelist to be integrated and not others, which may make for some interesting problems.)
This doesn't scale especially well -- you need to check each bugfix on each branch you care about, though it does lend itself to automation.
You can use the "unsupported" Perforce command interchanges to get a quick idea of what changelists have not been integrated from one branch into another. (In Perforce parlance, "unsupported" means something like "might not work the same in the next revision, but we think it could be useful so we'll release it anyway".) To see what changelists haven't been integrated from our example trunk to release branches, execute:
$ p4 interchanges //source/project/trunk/... //source/project/rel/...
Change 1236 on 2010/10/10 by user#client 'Fixed some bug you don't care about'
Change 1235 on 2010/10/09 by user#other_client 'Fixed some other random bug'
In this example, I haven't listed changelist #1234 because it's already been integrated into the release branch. One problem I've experienced using interchanges is it'll list every newer revision after an unintegrated change, even if the newer revisions themselves have been integrated, so if you're cherry-picking revisions for a release branch you may see changelists listed again. I use interchanges as a first pass to get a rough idea of what I need to integrate, then look at integrate to get a better idea of what's really missing.
(Perforce also supports a similar concept of "jobs", that let one attach particular fixes to particular changelists, but my organization doesn't use them so I don't know how well they work or whether they are propagated automatically on integration.)