Showing posts with label git. Show all posts
Showing posts with label git. Show all posts

Monday, May 2, 2011

Git and Subversion :- New Subversion Branch Created

If you have read any of my previous blog posts before, you know that I am use Git in order to track Subversion repositories. Recently, I had another experience that I had to resolve and I wanted to make sure that I share it with you.

The team decided to cut a branch of the code that I have been tracking. After they did that, I ran git svn fetch. After doing this, Git realized that a new branch was created and it started to search through the subversion repository to pull back any history that it might not have.

This probably is a good idea, if I were tracking the entire Subversion history, but I am not. The result was Git was starting to pull back history that I didn't have in my Git repo, nor history that I wanted. It would have taken hours to pull in that amount of history, and as I mentioned, I was not interested in retaining the whole entire repository.

In order to resolve this, I performed the following command:

git svn fetch -r:HEAD --no-follow-parent

I think that the most important part of this command is the --no-follow-parent. This tells git not to look back in time at the history, and just pull in the information from the specified starting point.

I hope that this helps someone else out there....

Pay it forward.

Thursday, April 14, 2011

Git Push :- Only Current Branch

Recently, when sharing a bare repository on my machine with one of the members on my team, we ran into a funny scenario. But first, it is probably worth mentioning the following information:

  • We are currently using git to push to svn
  • We have a master branch that is tracking the svn/trunk

I created a new bare repository that will allow us work together on a specific task. When using Git, you only want to push into a bare repository (a repo without a working directory), instead of the real one. He was able to pull the code just fine, but when he tried to push the changes into the bare repository, not only did it try to push the branch that we were currently working on, but it also tried to push the master branch as well. That is because the bare repository that I created, had a master branch, and so did his local, and therefore it was matching on that branches name. (Note: I was also experiencing this same behavior).

After Googling for an answer to the behavior and hoping to get the desired behavior of only pushing the changes from the branch that I am currently on, I found git push current branch, on StackOverflow. If you are like me, and want the desired behavior of only pushing the current branch that you are on to the remote repository, and not all of the branches, just run the following command in your git repository:

git config push.default tracking

There are other options besides 'tracking' but this is giving me the desired behavior that I was looking for...

Enjoy...

Tuesday, April 12, 2011

Git and Subversion :- Bringing others on board...

In the previous post, Pulling a Subversion Repository into Git Locally, I shared the process that I went through in order to pull Subversion into Git so that I can start using Git locally with Subversion as my remote repository. Since that time, I have been trying to figure out the best way to get Git to Subversion repositories set up for others on my team. I have gone through a lot of trial and error and now I believe that I have finally come up with an easy step-by-step solution.

Before I begin, let me first say that you probably want to follow these instructions for two main reasons:

Cloning a Subversion Repository is very time consuming
If you have never cloned a Subversion repository using Git, you will be amazed at how long this process can take (depending on how much history you want in Git). I typically chose 1000 revisions in the past, and that could take up to an hour or more. This is no fault of Git, instead, Subversion is to blame. With this process, only one person has to incur that time investment. Everyone else, can just reap the benefits without the hassle

Fetching too much data
This was the problem that has stumped me for months. While I was able to alleviate the first challenge of the time investment for everyone, I could not figure out why Git was trying to retrieve so much history from Subversion. This amount of history was even earlier than the 1000 revisions of the initial clone. Finally, I figured out that it has to do with a property called branches-maxRev. Through the use of this property, we can make sure that when you perform git svn fetch, that it will not attempt to retrieve any more history than necessary. So, let's get started

By this time, I am already assuming that you have followed the directions from Pulling a Subversion Repository into Git Locally, and you already have a Git repository with the amount of history from Subversion that you desire. From that point:

  1. Navigate to your git repo. Not the .git folder, but the folder containing that folder
  2. Open your browser to the git svn man page
  3. Scroll to the bottom section titled Basic Examples, and look at the third example
  4. Locally, start the git daemon server by typing: git daemon. This will start a git server on your local machine that will allow others to pull from you.
  5. Follow the instructions from the Basic Example starting with mkdir all the way to the end. Please note that the line that section that says server:/pub/project must be replaced with a valid git url (for instance git://jdcarlflip.blogspot.com/path/to/git/repo)
  6. Once you have finished those instructions, in your newly created repo, open the file .git/svn/.metadata
  7. Inside of there, you want to put a line under the uuid similar to the following branches-maxRev = 11111 where 11111 is the revision number that you do not want to go past. If you don't know what to put in there, look back at your original repo that you cloned from, and use the same number.
  8. After you have done this, type in git svn fetch, and it should not attempt to retrieve any revisions that are older than the ones you have already

If there are any questions, please let me know.....Enjoy.

Friday, July 9, 2010

Git feeling a little sluggish....?

So after working in my Git repository for the past couple of months, I started to notice that things are starting to run slower. I remember the days when I first started using Git, it was lightening fast. Now, it is still fast....but I have been missing the lightening.

That is until I was told about the command

git gc --aggressive

This command has brought the lightening back to fast in git.

Share and Enjoy.

Wednesday, April 28, 2010

Git and Removing Empty Directories

So, I encountered a very interesting annoyance yesterday with Git.  I can't say that it was a problem since it is working as designed, and there is a solution. 

I am tracking 7 different branches of Subversion in Git.  What is really interesting, is that I actively work on most, if not all of those branches.  When switching back and forth between branches, as you can imagine, there are some branches that has folders and code that other branches do not.

Git, by design, does not track folders.  The side effect of this is that when I am working on Branch A that has a folder F, then I checkout Branch B, which does not have folder F, that folder F still remains.  This is minor but it can quickly become very annoying especially when working in Java and there are a ton of empty packages (folders) in your source directory.  So what do you do...?

There is a command that will clean up all of the files that are not part of your git repository - including the folders.  This command is:

git clean -fd

Keep in mind, that any files or folders that are not part of the git repository will be removed when you issue this command.  If instead, you would like to do a dry run and see what exactly would be deleted prior to actually deleting them, you can run

git clean -fdn

Happy Coding...

Monday, April 26, 2010

Git / Subversion :- Retrieving an Old Branch

When I first started using Git and Subversion together, I decided that I didn't want the entire Subversion repository on my machine. Instead of cloning the entire Subversion repository, I cloned the last 1000 revisions. This has been working very well for me until today.

Today, we discovered a defect on a branch that was created and deployed well before the starting point in Subversion that I decided to clone from. If instead, the branch was created within the last 1000 revisions, I would have had that branch in my local Git repository. I could have checked that branch out, created a tracking branch, made the necessary code changes, merged it back into the master and sent it upstream to Subversion. But, this was not the case. The Subversion branch that needed code change was not in my local Git repository. How would I get it in there?

After doing some browsing on the internet, I think I came up with a solution that was inspired by a blog post titled Complex SVN repository conversion to Git, by Simeon Pilgrim. While Simeon was not dealing with the same problem that I was dealing with, the solution that he used for his situation could easily be molded to help me with mine.

What I ended up doing was hand modifying the config file that is located within the .git directory in the repository. I added another remote Subversion repository entry. This entry was just going to be used to track the one branch. Here are the details of that entry:


[svn-remote "0.5.0"]
url = http://subversion.sagetech.com/svn/somethingReallyCool/branches
fetch = 0.5.0:refs/remotes/svn/0.5.0

This entry above is telling Git that I have a remote Subversion repository that will be aliased as 0.5.0. It also tells Git the URL of the repository as well as the path that should be used for fetching. The fetch actually specifies two paths separated by a colon in the following format "origin:destination". This line is saying that it will pull the code that resides in...

http://subversion.sagetech.com/svn/somethingReallyCool/branches/0.5.0

and put it into the Git remote branch at refs/remotes/svn/0.5.0.

After this entry was made into the .git/config file, all that was left to do was to fetch the code. That was done with the following command:

git svn fetch -r1200:HEAD 0.5.0

This fetched from the Subversion branch 0.5.0 into my Git Remote branch all of the revisions starting at 1200, and allowed me to fix the defect and publish back to the 0.5.0 branch.

Happy Coding

Monday, April 19, 2010

Git Revert to the Rescue...

Once again, Git has saved yours truly.

One of my current responsibilities is to merge a branch within Subversion to the main code line (trunk). Usually, this doesn't require a lot of effort in order to complete. For this merge, since there were relatively few changes, I decided to perform the merge using the command line.

I specified my range of revisions that I would like merged down to the trunk, resolved all of the conflicts, and then committed the merge to Subversion. Later, I realized that I did not specify the correct range of revisions, and therefore, the merge was incomplete. I was just about to revert my changes in the Subversion repository, when I realized that there had been some commits done to the trunk after my merge. Doh!!!

Why is this such a problem? Well, it is a problem because if I was to roll back the Subversion repository to the point right before the incomplete merge that I performed, then I would also be removing the commits of my teammates. That would not make me too popular amongst my co-workers.

At this point, what could I do? One option would be to take the commit that occurred after my incomplete merge and save it off somehow using a patch tool, then roll back the subversion repository, then reapply those changes. Another option would be to figure out all of the changes that I made as part of my incomplete merge, and roll each file back one by one to the previous version. Both of these options sounded horrible and time consuming. Luckily, I could use Git in order to solve this problem.

Git Revert to the Rescue

Git has a great feature called revert. In a nutshell, the revert feature of Git allows you to specify any commit, create a reverse-patch for that commit, and commit it to the repository using one command. In other words, it backs out the changes of a commit. For example, let's say that your repository has the following 4 commits:


A-B-C-D

You realize that there is a bug in the commit titled 'B', and you would like to roll the code back. You can do that using Git by typing


git revert B

which would change your repository to:


A-B-C-D-E


The commit titled 'E', is actually a reversal of the commit B.

Needless to say, this little trick saved me a lot of time and effort. All I did was revert the merge commit, and attempted the merge again, this time making sure that I specified the correct range of revisions. For this little feature alone, I am grateful that I am using git.

Happy Coding

Friday, April 16, 2010

Git :- Unrealized Productivity Gain

After showing a co-worker my workflow using Git integrated with Subversion, he pointed out a productivity gain that I am getting that I have been taking for granted.

When I was using Subversion, I would have multiple directories that would represent different code lines. I had a directory for the trunk, and a directory for each of the branches of code for our code base. On top of that, when I wanted to work in one of the other code lines, I would have to restart my IDE, and then point it to the correct code line. This did not take too long to do, however, considering the amount of times I jump between code lines, it was definitely time that was not well spent.

Using Git, I now only have one directory with all of my code. If I want to switch to a different branch, then all I have to do is perform a checkout of that branch, and refresh the code in my IDE. Simple, elegant, fast and effective.

Yet another reason why I am loving Git.

Tuesday, April 13, 2010

Pulling a Subversion Repository Into Git Locally

Over the past month, I have really enjoyed using Git with Subversion. However, when I was thinking about how I got Git all setup to access Subversion, I realized that I can't remember exactly how I did it. So in the interest of remembering how to get Git setup to work with Subversion, I am writing this post for myself and anyone else who is interested in using Git in a Subversion environment.

After installing Git, you are going to want to determine the URL of the Subversion repository that you are going to want to integrate with. For our purposes, let's use the Open Source project AppFuse, whose Subversion repository is hosted at https://appfuse.dev.java.net/svn/appfuse/trunk.

First thing to do is to clone the repository to your machine. This process of cloning is what is going to convert the Subversion repository into a local Git one. At this point, I am not interested in cloning the entire repository (all of the branches, tags). I am also not interested in cloning all of the revisions (at the time of this blog post, their Subversion repository is on revision 3333). Instead, I only want to clone the trunk with the past 100 revisions. Here is the command necessary to do just that:


git svn clone https://appfuse.dev.java.net/svn/appfuse -r3330:HEAD --prefix=svn/ -T trunk -b branches -t tags appfuse.git

(You can choose to omit the -T, -b, and -t options, if you so desire. We can always add those details later.)

If you are prompted for a user id and password, use the account 'guest' without a password.

During the cloning process you are going to notice that git is actually mapping the 100 commits in Subversion to a Git commit object in your local repository. As you might imagine, this process could take a very long time, depending on how many revisions you are cloning into your local repository.

After your clone has completed, you should have a directory called appfuse.git. Move to that directory and type the following

git log -3 --stat


This will show the last three revisions that have been made to this source code. The first commit looks like this:

Author: mraible 
Date:   Sat Feb 27 15:54:03 2010 +0000

    Turn off EhCache update checking.
    
    git-svn-id: https://appfuse.dev.java.net/svn/appfuse/trunk@3333 2aeb74e6-0f1c-0410-991c-92d95bb9df37

 web/common/src/main/resources/ehcache.xml |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
The most interesting thing about this log is the fact that you can tell what Subversion revision it came from by the line that begins with git-svn-id. You can see that it comes from the revision 3333. There are many other features of git log that I am not going to talk about, but do encourage you to look into.

Congratulations, you have successfully pulled the Subversion repository into Git locally. In the next couple of blog posts, I will spend some time discussing how to commit changes back to the repository, as well as how to track and commit to branches in Subversion.

Happy Coding.

Monday, April 12, 2010

Git Interactive Adding...now you tell me...

First off, major thanks to Scott Chacon and his video post on how to do Interactive Adding in Git. Unfortunately, I am only now getting a chance to review this video, since it was crunch time at work today...

I spent most of the day today hunting down a defect. This defect was a good one. You know the kind. The kind that really stretches your brain and gives you a chance to flex your skills as a Software Developer. Of course, as always, there was a logical explanation for the erroneous behavior that we were seeing, however, it took quite a lot of time, and a lot of Tracer Bullets, in order to find the problem. After finding the problem, we made the appropriate code changes...I love team coding...and then I wanted to commit those changes. This is where Interactive Adding in Git would have helped out a ton...

I wasn't interested in committing all of those tracer bullets, instead, all I wanted to commit was the actual fix. Using interactive adding, I could have staged the changes that actually fixed the issue in one commit, and then I could have added the Tracer Bullets as another commit. Since these were separate commits, I could have then switched back to my master branch, and cherry picked the commit that had the fix in it. (Remember, I do not develop on the master branch and instead choose to merge in changes from other branches once I have completed development and testing). This would have resulted in a very nice and clean fix to the master branch.

Unfortunately, since I am not yet the git slinger that I aspire to be, I had to commit the tracer bullets and the fix underneath the same commit and merge all of those changes down to the master branch. So, I have a little code clean up to do...doh!!!

After watching Scott's video, I am more confident in my interactive adding git skills, and I look forward to using them the next time I want to selective commit a portion of my changes.

Happy Coding...

Thursday, April 8, 2010

Distributed Version Control Systems.....how I love thee...

Today, I was working with a developer at his station and we made some changes to some code. I asked if he could commit those changes, and he told me that he was not ready to commit those changes because he had made changes elsewhere in the system and those other changes were not yet ready. This reminded me of why I have made the switch to using Distributed Version Control.

You see, when you are using Distributed Version Control Systems, you can adjust your workflow in such a way that you do not run into these types of scenarios. With the advantage of creating branches of code locally, you can work on completely different efforts simultaneously. Currently I have 7 different branches that reside locally for one of my customers. This allows me to switch between different efforts that are currently underway. More than that, since I am using Git, I am able to synchronize with my customer's Subversion repository and delivery the changes that I want to delivery and retain the ones that I don't.

To illustrate the advantage of using DVCS, let's take the scenario I mentioned earlier. A developer approaches me and asks me for some help and would like to pair program a specific feature. I am smack dab in the middle of working on something (I mean the code doesn't even compile). Since I am using Git, I am able to commit this code that doesn't compile and create a new local branch based on the trunk of the source code that is in Subversion. I realize committing code that doesn't compile is a big NO-NO, but I believe that helping your co-workers / customers is much more important (besides, I would only be committing those changes locally, and not pushing them to Central repository anyways). Now the code that resides on my machine looks exactly like the code that is in the repository. We make the necessary code changes, I commit them locally to my local repository and push them back up to Subversion. My co-worker / customer goes on his merry way, and I switch back to the branch that I was working on when they came over for assistance.

DVCS...it is a beautiful thing...