At my job, we recently switched from SVN to Git. We use EGit for the integration with eclipse
Now, I have to ask the question : When we pull a lot of changeset from origin/master, there often are conflict, especially when we move classes from package to package. Fine we think, we'll just merge them then commit, then push the merge. But no, when we do that, EGit still show incoming changeset from the server, and when we pull them, it create some conflicts, again, usually the same annoying import we just merged. We have to do it 2 to 4 time before finally it is merged
Why doesn't it just conflict everything once, then be done with it?
Right now I don't get at all why it operate like this. And of course 3 out of 4 time it happen on my boss computer, and that is bad (TM)
And what is the correct workflow when we want to fetch some changeset and merge them? In eclipse please, some dev don't feel very easy with the command line.
Thank you
did you commit resolution of conflicts ?
git add f1 f2
git commit f1 f2
Quite a few month later, I can say that this was actually a bug in EGit that is now fixed. Sometime when doing a pull, the operation would fail (as opposed to be in conflict). That would lead to a corrupted state in Eclipse, and of course trying to merge in that state would not work.
If you ever suffer from that problem, just update your software. Note that it still affect old versions of Eclipse so if your still on something like Helios (like my boss was) you should probably upgrade the whole IDE.
Moral of the story : keep your software up-to-date.
Related
I admit that I have very little experience with source control and git, however, in my past projects it has been useful to make commitments as backups. During this project, I decided to test out making a new branch. After working in it I decided to click 'checkout' master not knowing what it really did, now all my commits 2 weeks prior have been deleted, it's like I traveled back in time and all those commits I made never existed. All the files I had been working on are now gone and nowhere to be seen. I searched trash, I searched the project folder. They vanished. Did I screw up? Is there any way to recover this files? I searched all the branches without any luck. Thanks.
I don't know how Xcode's UI spells it, but the git command is git checkout #{1}. Look up reflogs and revisions, #{1} is how git spells "what I had checked out just before I did whatever just changed it".
Did I screw up?
Not necessarily! If you made commits on the new branch, everything is still there, on the new branch you created and worked on. So just checkout that branch again, and it will return!
now all my commits 2 weeks prior have been deleted
Ah, so you did make commits. In that case, be assured, nothing is lost.
But if you did not commit on the new branch — if you checked out master without committing your work from the new branch you were working on — then yes, you screwed up and it is all gone. The substance of git is commits, and whatever is not committed is not in the purview of git and is subject to unexpected loss. Loss due to checkout is a classic git trap; you would think it would warn you of the danger, but it doesn’t always do that.
While working, I make lots of revisions. Whenever the code is in reasonable shape, I like to commit. But not all of those commits are interesting. So I make these commits to the local disk or a private server. It looks something like this:
I fetched package Foo in the morning, so it's version is FamousSmalltalkGuy.14.
I commit in the morning (15), at lunch (16), and in the evening (17) locally. Now package Foo locally is up to DanielLyons.17.
Looks like Famous Smalltalk Guy pushed version 15 to Smalltalkhub.
I merge FamousSmalltalkGuy.15 with what I have in my image, producing DanielLyons.18.
Now I want to push DanielLyons.18 up to Smalltalkhub. What's the right thing to do?
Copy the version (clicking the Copy button in the Monticello UI).
This feels wrong because there will be a discontinuity from FamousSmalltalkGuy.15 and DanielLyons.18.
Commit a new version in the Smalltalkhub repository, manually writing DanielLyons.15 in the box.
This feels wrong, because it seems to confuse my local image. After all, it's seen a DanielLyons.15 before, and this isn't it.
I feel sure that there's a right thing to do here, but I don't know what it is. If anyone can shed some light on the right Monticello workflow for simultaneous collaborative development, I'd greatly appreciate it. Thanks!
You should copy all your versions to remote repository, otherwise you will loose valuable history. Curently because of how Monticello is implemented it produces a lot of broken links to ancestors, as people forget to copy intermediate versions from their local storage. And yes, version numbers are stupid. You cannot have sequential version numbers in distributed versioning, so I prefer to leave commit names as they are and just copy everything to the remote repository
Backport
Monticello has a so-called backport changes feature, that lets you apply changes you
accumulated over several commits plant onto an older version. It is seldom used, tho.
Branch
Another process would be to locally make a branch and only at the end make a merge with the version you want to commit on.
A Monticello branch is done by appending -branchname to the package name:
Foo-DanielLyons.18 becomes Foo-mybranch-DanielLyons.18
If Monticello refuses to merge, you can say “adopt as ancestor” and specify, that your new version has both your branch and the original commit as ancestors.
The process then goes like this:
Fetch the current version, say Foo-FamousSmalltalkGuy.14
Do your stuff and commit it like:
Commit your version Foo-myImportantTopic-DanielLyons.15
Commit your version Foo-myImportantTopic-DanielLyons.16
Commit your version Foo-myImportantTopic-DanielLyons.17
Adopt as Ancestor the version Foo-FamousSmalltalkGuy.14
Commit to the remote as Foo-DanielLyons.15
Suppose I have the following senario:
Trunk is my main development line where programmers commit to when done.
Branch V1.0 is a branch I created when releasing version 1.0.
The programmer is working on the trunk but needs to switch to the branch in order to fix bugs.
When switching back to the trunk Subversion will give me the latest in the SVN repository which does not include the recent changes.
So, in order to switch he will have to commit what he has because otherwise the changes are "lost". I know they are still kept in the local repository but it would still mean restoring them one by one once he switchesback.
Am I missing something here?
Edit:
Now I am thinking down these lines:
Each programmer would have his own "private" development branch off of the trunch. He could commit to there whenever he wants. When he has finished what he has written he can them merge it into the trunk. He starts again for the next assignment.
If at any point he is required to fix a bug in some other release he can just commit to his own private branch, fetch the odl release and fix it. Then, after committing the changes to the fix, he can easily switch back to his own development branch.
Would that work?
I think that subversion is not thought for switching as you described. A solution would be to have two workspaces, one for the branch and another one the trunk, so you can switch from one to another without problems. I know it is not a nice one.
Consider switching to a version control tool that is better suited for your approach. My own suggestion is Mercurial, coupled with MercurialEclipse. The only drawbacks I'm aware of are that Subversion is better suited to store binary files and that Mercurial's subrepositories don't work so well as Subversion's externals.
In Mercurial your programmers would be able to commit their changes to their private repositories, merge and commit locally again, and then push the resulting changes to an official repository, from which other programmers would pull them into their own private repositories.
The best solution for such purposes is to have two separate working copies. One for working with trunk and one working with the branch.
We have a small programming shop of at most 5 people working on a single project. I fully grok why DVCS is better for open source projects, and for large companies, but what advantages does it have for smaller companies other than "you can work on the airplane." Which would require extra SA work to make sure that our repositories on DEV boxes was properly backed up every night.
We also a have several non technical people (artists, translators) who can (sort of) deal with SVN, in peoples experience how much training is required to get them to move to a DVCS?
I'm going to speak from my experience, which is primarily with SVN and Hg, often working with designers and programmers who are not comfortable with version control.
My big beef with SVN and other CVCS's I've used is that they block you from making commits, not just when the network is down, but also in case of a conflict (or worse, someone locking a file so no one else can make changes to it!). You could of course commit to a branch, but between network bandwidth required to switch branches and the pain involved in merging, you still have a problem.
Of course, SVN blocks you from committing conflicted files so that you don't accidentally overwrite someone else's work; SVN requires you to at least acknowledge that you know one version or the other (or a custom combination of the two) is right. Mercurial, however, has a better solution (2, actually):
1. You can always commit to the local repository now and merge later. (All DVCS's have this feature.)
2. Even if you pull or push conflicting changes, instead of being blocked from committing, you have multiple heads via anonymous branches. (Sorry I can't really explain this in detail here, but you can google it.)
So your workflow goes from:
1. Get the latest, make changes, test them.
2. Get the latest, resolve conflicts, test the result.
3. Commit.
and becomes:
1. Get the latest, make changes, test them.
2. Commit (so you have a place to fall back to).
3. Get the latest, resolve conflicts, test the result.
4. Commit and push.
That extra commit means you're doing less work per commit, so you have more checkpoints to fall back on. And there are other ways you can make more commits without getting in others' way.
SVN is just slow enough to break my concentration and tempt me to go to facebook; mercurial is fast and git is faster. The speed issue becomes very important when reviewing a log or changes to a working copy. With TortoiseHg, I can click through a list of files, and instantly see changes to that file; it takes about a couple seconds per file with TortoiseSVN + WinMerge (not sure how much of this is due to the DVCS). The more I use these tools, the more I feel that a VCS needs to be fast, just like a text editor or a mouse cursor--fast enough that you shouldn't require the network to do it.
Subjectively, I find TortoiseHg to be a heck of a lot easier to use than TortoiseSVN (or other tortoises I've used). TortoiseHg is mutli-platform, too. :)
One more thing: As I understand, a SVN working copy is defined recursively: Each folder is a working copy. This allows you to do some fancy-pants stuff (e.g. having a working copy that contains folders from disparate locations in the repository). I don't know if Hg has a similar feature, but in my experience, SVN's implementation of this feature causes only problems where I work, especially for those not quite comfy with SVN. When they copy-and-paste a WC folder on their machine via the OS shell instead of via svn copy, it goofs up their WC. I've goofed up my WC this way as well. It's less of a problem with Hg--you normally work with an entire repo at once, whether you clone, update, or commit.
SVN improved a lot concerning merging since its release. But it still lacks file rename tracking, often resulting in tree conflicts. Renaming is the killer app of distributed version control tackles this issue, adding some interesting links in the comment section.
DVCS lets you push to a central repository, at the cost of one additional command compared to Subversion. Occasional users should be able to adapt to this minor change in workflow. But giving the freedom of 'local' commits and branches to power users without cluttering a central repository.
Concerning tooling, which might be of importance for user acceptance, Mercurial is on par with Subversion.
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