I am working under a Java project together with one of my collegues. Project sources are hosted in private GitHub repository. We are both using IntelliJ Idea 13 to work with it - commit changes and update project from Git repository. The whole IntelliJ Idea project is also in GIT repository.
The issue is that sometimes (approximately after a few commits/updates, can't say for sure since that happens randomly) Idea decides to remove ALL of my local changes and just take whatever comes with an update from Git. Under ALL I mean ALL - all new files, all changes, all resources - whatever was changed locally and not yet committed. Usually update goes well and even if something should be merged - Idea offers a merge dialog where issues can be resolved, so this is not about merging changes for sure.
It is also not an OS-related issue since we've been working on different platforms (at least Win XP/7/8, Ubuntu and Mac OS X) - that issue happens everywhere.
I have been looking for the solution of this issue for some time now and didn't find even a single thread about it, so I have decided to ask here - probably someone might give me some tips. Probably I don't know something about GIT since I didn't actually work with it a lot.
Since this case it pretty vague I am not sure which information I should add to the topic to clarify the situation.
Thanks a lot in advance!
P.S.
A wild guess - IntelliJ Idea has a workspace.xml file in its project files which represents user-related settings of work area plus some other stuff - it is also in GIT in our project and ocasionally gets committed with other changes, might that cause this issue?
Related
I am creating a project that has two flavors
one for enterprises and one for families .
the deferences are simple really : changed labels(property) , changed colors(CSS) , a few deleted features...
i don't want to start a new project and copy the whole enterprise to the family version because that would mean that each bug must be solve in both .
technology used :JSF,Jquery,Hibernate and eclipse as an IDE also I am deploying to Jboss.
i dont know where to start but i have the following thoughts:
solution attempt 1 :
along time ago when i used to develop J2me application on netbeans we used to have something called configurations where we can choose to include deferent segments of the code depending on the configuration(device) so we would end up having multiple executable files.
solution attempt 2:choose which code is common and move it to a separate location and include it in both projects (this would be painful to implement and also i need to replicate some fixes some times)
is there any good solution to this issue ?
thanks
Consider using a repository (git, svn) - create a branch for each of the versions, and then when you fix something on one of the versions, merge it to the second. With git you can have a local repo just for your own on local machine, and it's really simple to set up.
This may be a stupid question, but after several times trying to get this right I'm getting frustrated. I want to use github to host my project, we are 2 people working on the project and the aim was to share the work. And help each other.
I managed to create the resepetory, and committing to master branch. If the other guy deletes the whole project he gets the latest updates, but I'm sure this is not the way its supposed to work.
Lets say I commmit a new class file. I commit this file, how could the other person download this file? We've tried pull, synchronize etc etc without any luck. The only way we have found to give him "my" latest updates is for him to delete all content and make the project from scratch.
What am I missing? How can we synchronize workspaces? So I can see and download his changes when i open Eclipse? (We are not working in the same class). So really all I want to do is download he's latest commits.
EDIT : My solution was that my partner was working in a copy of the local git workspace. So instead of modifying the local repo he was modifying a copy of it inside the Eclipse workspace. And because of this nothing updated when he did the pull. I also switched from Egit to GitHub command line tool, and I'm in love. Thanks everyone :)
Normally with GitHub, all of what you have described works perfectly, I have not had any kind of similar problems.
One thing about git, a commit is a bit different than a commit in SVN. With git, you use push and pull to interact with your remote repository.
I am not sure what you mean when you say:
If the other guy deletes the whole project he gets the latest updates,
but I'm sure this is not the way its supposed to work.
That being said, I have never used Egit, I prefer to stick to the command line for all my git needs. I have had issues with other software (Sublime Text 2) where I would have to exit the editor, then run all my commits and other git actions. I do not know how well Eclipse plays with git in general.
Try to have your partner run git remote -v just to make sure he is tracking the repo properly. Also, do you know if he set up an SSH key for GitHub, or you sending your pushes and pulls via https?
Keep in mind this is pretty hard thing to help you out with since I am not sitting at your computer. GitHub Help has some very good walkthroughs on setting up git and remote repositories.
Also, I highly recommend the time to go through CodeSchool intro to git. If this is your first time using Git, this is the best starting point.
There are much more complicated scenarios, but basically, you need to "push" your commits to the upstream, and pull your colleague's.
Clone the repo. By cloning it you will guarantee that it has an "origin", the github remote. You make changes in your local repo, committing them as you go. When you are at a milestone, use Team > Push to push all of your commits to github. Your colleague will pull them, as described below.
When you try to push, you may discover that your colleague has pushed changes and that git will not allow you to push until you merge. Try Team > Pull which will merge the remote changes into your local repo. If there are no conflicts, you can now push. If there are conflicts, fix them and then commit. Then push.
This is a substantial simplification but may get you started. The main point is that the equivalent of a SVN commit is, in git, two, maybe three, operations: add, commit, push. Git pull is vaguely analogous to SVN checkout.
Take a day to read up on git. There's great documentation at GitHub. Once you get the hang of it, you'll love it.
When using git to collaborate on a project, you are managing both a local and remote repository. When you commit, you are only saving changes to your local repository. After committing, you need to do a push in order for your changes to be saved to your remote repository. After doing that, if your collaborator does a pull he will get your changes.
My understanding of git add is that you're basically saying to your local git repo "Yes, I'm sure I want to make these changes."
My understanding of git commit is to actually save the changes to your local HEAD branch. At this point they are actually in version control, but are only local to your instance of git.
My understanding of git push is to propagate your saved (committed) changes to the master repo, so other developers (or perhaps a CI build) can pull them down for themselves.
If anything that I have said so far is wrong or is misleading, please begin by correcting me. Assuming I'm correct in my understandings, I originally had a package in my Java project that looked like this:
com.myapp.server.servlets
FizzServlet
BuzzServlet
But then I decided to refactor the names and of a few things, as well as both adding & deleting some new files/packages:
com.myapp.server.servlet
FizzesServlet
WidgetServlet
com.myapp.server.servlet.impl
FizzesServletImpl
WidgetServletImpl
Overall, I account for 5 changes to this directory:
Changed the name from "com.myapp.server.servlets" to "com.myapp.server.servlet"
Changed the name from "FizzServlet" to "FizzesServlet"
Deleted the BuzzServlet altogether
Added a new WidgetServlet
Added a new com.myapp.server.servlet.impl package with two child files
Do I have to do any sort of special command magic here, because I did so much refactoring, or can I just run something like git push * to push everything to GitHub? In the SVN Eclipse plugin, if I renamed a package or source file, and then tried committing that change, I would often lose the file altogether (locally) and have to restore from local history. Even then, I got burned far too many times to count and lost a lot of work. I'm hoping not to get the same experience with Git.
From the way you're very careful about pushing, your understanding of git push is not quite complete. push will literally only push your commits to your remote -- that means, it will copy the exact state that you saved in the commit(s) you have made since last pushing. In Git, every commit is a snapshot of all the files in a repository (it does in fact record all files, and not just the changes). So what you see locally after committing will be exactly what's copied onto the remote when pushing.
When you push, one of two things can happen:
The push succeeds, in which case all is well and the state of the remote mirrors the state of your local repo (to emphasize this, remember that git commits are identified by their SHA hash -- if the commit were different, so would the hash be)
The push gets rejected, because it is not fast forward. This happens when someone else has pushed commits onto your remote since your last pull/fetch, and it is the equivalent of the nasty and oft-feared conflict when trying to commit in SVN. However, your local state is not affected by this. You will have to resolve the conflict (a) dropping your commits and accepting the state of the remote (git reset is used for this) or by fetching from the remote and (b) merging your local changes, thereby creating a merge commit which will indicate the diverging and re-converging of your history, or alternatively (c) rebasing onto the remote, to produce linear history.
The conflict resolution case will take a bit more looking into, but the actions required are well-described in the Pro Git book (chapters Branching, Merging, Rebasing).
A conflict can only happen if someone else can push to your remote, or if you push to your remote from another computer. If you are working in a single-user single-computer scenario (at least for now), there will be no conflict when pushing.
The problem scienario is as follows (Note: this is not a cross-jar dependency issue, so tools like JarAnalyzer, ClassDep or Tattletale would not help. Thanks).
I have a big project which is compiled into 10 or more jar artifacts. All jars depend on each other and form a dependency hierarchy.
Whenever I need to modify one of the jars, I would check out the relevant source code and the source code for projects that depend on it. Modify the code, compile, repackage the jars. So far so good.
The problem is: I may forget to check one of the dependent projects, because inter-jar dependencies can be quite long, and may change with time. If this happens some jars may go "out-of-sync" and I will eventually get a NoSuchMethodException or a some other class incompatibility issue at run-time, which is what I want to avoid.
The only solution I can think of, the most straighforward one, is to check out all projects, and recompile the bunch. But this takes time, especially if I re-build it every small change. I do have a continuous integration server, that could do this for me, but it's shared with other developers, so seeing if the build breaks is not an option for me.
However, I do have all the jars so hypothetically it should be possible to verify jars which depend on the code that I modified have an inconsistency in method signature, class names, etc. But how could I perform such check?
Has anyone faced a similar problem before? If so, how did you solve it? Any tools or methodologies would be appreciated.
Let me know if you need clarification. Thanks.
EDIT:
I would like to clarify my question a little bit.
The ultimate goal of this task is to check that the changes that I have made will compile against the whole project. I am looking for a tool/technique that would aid me perform such check.
Consider this example:
You have 2 projects: A and B which are deployed as A.jar and B.jar respectively. A depends on B.
You wish to modify B, so you check it out and modify a method signature that A happens to depend on. You can compile B and run all tests by itself without any problems because B itself does not depend on anything. So you happily commit your changes.
In a few hours the complete project integration fails because A could not be compiled!
How do I avoid this?
The kind of tool I am looking for would retrieve A.jar and check that all dependencies in A on the new modified B are still fine. Like a potential compilation error that would happen if I were to recompile A and B sources together.
Another solution, as was suggested by many of you, is to set up a local continuous integration system that would recompile the whole project locally. I don't mind doing this, but I want to avoid doing it inside my workspace. On the other hand, if I check-out all sources to another temporary workspace, then I need to mirror my local changes to the temporary workspace.
This is quite a big issue in my team, as builds break very often because somebody forgot to check out (or open in Eclipse) the right set of projects. I tried persuading people to check-out source and recompile the bunch before commits, but not only it takes time, it needs running quite a few commands so most people just find it too troublesome to do. If the technique is not easy or automated, then it's unusable.
If you do not want to use your shared continuous integration server you should set up a local one on your developer machine where you perform the rebuild processes on change.
I know Jenkins - it is easy to setup (just start) on a local machine and I would advice to run it locally if no one is provided in the IT infrastructure that fits your needs.
Checking signatures is unfortunately not enough. Having the correct signatures does not mean it'll work. It's all about contracts and not just signatures. I mean what happens if the new version of a library has the same method signature, but accepts an ArrayList parameter now in reversed order? You will run into issues - sooner or later. I guess you maybe consider implementing tools like Ivy or Maven:
http://ant.apache.org/ivy/
http://maven.apache.org/
Yes it can be pain to implement it but once you have it it will "guard" your versions forever. You should never run into such an issue. But even those build tools are not 100% accurate. The only proper way of dealing with incompatible libraries, I know you won't like my answer, is extensive regression testing. For this you need bunch of testing tools. There are plenty of them out there: from very basic unit testing (JUnit) to database testing (JDBC Proxy) and UI testing frameworks like SWTBot (depends if your app is a web app or thick client).
Please note if your project gets really huge and you have large amount of dependencies you always not using all of the code there. Trying to check all interfaces and all signatures is way too much. Its not necessary to test it all when your code use lets say 30 % of the library code. What you need is to test what you really use. And this can be only done with extensive regression testing.
I have finally found a whole treasure box of answers at this post. Thanks for help, everyone!
The bounty goes to K. Claszen for the quickest and most input.
I'm also think that just setup local Jenkins is a best idea. What tool you use for build? Maybe you can improve you situation with switching to Maven as build tool? In more smart and don't recompile full project if you don't ask it directly. But switch to in can be HUGE paint in the neck - it hardly depends on how you project organized now...
And about VCS- exist Mercurial/SVN bridge - so you can use local Mercurial for you development ....
check this link: https://www.mercurial-scm.org/wiki/WorkingWithSubversion
There is a solution, jarjar, which allows to have different versions of the same library to be included multiple times in the dependency graph.
I use IntelliJ, not Eclipse, so maybe my answer is too IDE-specific. But in IntelliJ, I would simply include the modules from B into A, so that when I make changes to A, it breaks B immediately when compiling in the IDE. Modules can belong to multiple projects, so this is not anything like duplication, it's just adding references in the IDE to modules in other projects.
We are using Hudson for our Continuous Integration server and it's great. We have 2 issues with it, which are mildly related.
https://hudson.dev.java.net/issues/show_bug.cgi?id=2736 The build order in Hudson means that the downstream dependencies get built a lot more than they need to be. Hopefully this issue will be addressed soon.
Since these things are getting built so frequently, the build history is massive. We really don't need 1000 build items in the history for some of the jobs.
My question is about point 2. I would like something like a job or plugin to delete old artifacts. Keeping say the last 20 builds of everything around would be fine. At the moment it seems unbounded, which isn't great from an operations perspective.
UPDATE: As per Norbert's answer, it is in the job configuration. In the 1.300 UI, there is a "Discard Old Builds" checkbox, which allows this to be configured.
There is such configuration in our hudson build server. In the project config I can chose between an amount of builds or a period of time to keep. I don't think I installed aplugin for this