How-To Fork Git Repositories on Visual Studio Online

Visual Studio Online

Microsoft rebranded Team Foundation Service as Visual Studio Online with the launch of Visual Studio 2013 last fall. Visual Studio Online enables team collaboration using either Git or TFS source code control directly inside Visual Studio 2013, web browser, or the command line. Microsoft is entering a space dominated by GitHub & Bitbucket, and developers will seek familiar workflows and features offered by by these platforms.

GitHub Fork

GitHub established the paradigm of forking, upstream repositories, and pull requests for a lot of developers. VonC put together a nice graphic to illustrate the relationship of repositories in his response to a Stack Overflow question on the topic.

Fork

GitHub simplifies the process of forking an upstream repository with the simple click of the Fork button:

ForkButtonCropped

Visual Studio Online Fork

Visual Studio Online might not currently have a Fork button but the process of forking Git repositories between accounts is quite straightforward and involves:

  1. Creating the target project to contain the fork repository
  2. Cloning the upstream repository
  3. Adding a remote origin link to the fork
  4. Pushing the cloned repository to the fork origin

In this scenario, I will fork a Git repository name VisualStudioOnlineFork from an upstream master repository located in woodcp.visualstudio.com to a fork project located in toddwood.visualstudio.com using the owner account of the fork repository. The fork project owner account had access granted to the upstream repository by the upstream owner account.

UpstreamRepo

Create Fork Repository

Login to the fork account and create a new team project named the same as the upstream repository. Technically the names do not need to match but that is the convention established by the GitHub Fork button.

CreateTargetFork

Once the project is created, Visual Studio Online will display the empty repository and instructions on how to set the remote and push the upstream or any existing repository:

BareRepository

Clone Upstream Repository

With the target and empty fork repository created, we can clone the upstream repository to our local computer. Access the upstream repository in Visual Studio Online if you need  to identify the clone Url:

CloneUrl

A nice feature of the git clone command is to set the origin name to upstream when cloning the master repository using the –origin=upstream directive:

C:\> mkdir fork
    Directory: C:\
Mode                LastWriteTime     Length Name
----                -------------     ------ ----
d----          1/3/2014   8:58 PM            fork

C:\> cd fork

C:\fork> git clone --origin=upstream https://woodcp.visualstudio.com/DefaultCollection/_git/VisualStudioOnlineFork
Cloning into 'VisualStudioOnlineFork'...
remote:
remote:                    fTfs
remote:                  fSSSSSSSs
remote:                fSSSSSSSSSS
remote: TSSf         fSSSSSSSSSSSS
remote: SSSSSF     fSSSSSSST SSSSS
remote: SSfSSSSSsfSSSSSSSt   SSSSS
remote: SS  tSSSSSSSSSs      SSSSS
remote: SS   fSSSSSSST       SSSSS
remote: SS fSSSSSFSSSSSSf    SSSSS
remote: SSSSSST    FSSSSSSFt SSSSS
remote: SSSSt        FSSSSSSSSSSSS
remote:                FSSSSSSSSSS
remote:                  FSSSSSSs
remote:                    FSFs    (TM)
remote:
remote:  Microsoft (R) Visual Studio (R) Team Foundation Server
remote:
Unpacking objects: 100% (3/3), done.
Checking connectivity... done

Configure Remote Origin

At this point, we have cloned the repository with only a remote named upstream pointing to the master repository. Referencing the bare repository instructions in the fork repository, we add the remote origin pointing to the fork repository location:

C:\fork> cd .\VisualStudioOnlineFork

C:\fork\VisualStudioOnlineFork [master]> git remote add origin https://toddwood.visualstudio.com/DefaultCollection/_git/VisualStudioOnlineFork

Push to Fork

Once again, using the bare repository instructions we perform a git push -u origin –all to complete the fork process:

C:\fork\VisualStudioOnlineFork [master]> git push -u origin --all
Counting objects: 3, done.
Writing objects: 100% (3/3), 250 bytes | 0 bytes/s, done.
Total 3 (delta 0), reused 0 (delta 0)
remote: Analyzing objects (3/3) (2 ms)
remote: Storing pack file and index...  done (800 ms)
To https://toddwood.visualstudio.com/DefaultCollection/_git/VisualStudioOnlineFork
 * [new branch]      master -> master
Branch master set up to track remote branch master from origin.

The fork of the upstream repository is now complete and available in Visual Studio Online:

ForkRefreshView

Visual Studio Online Merge Upstream Changes

As time progresses the upstream repository will diverge from the forked repository. The fork maintainer can easily merge the upstream changes by fetching from upstream, merging master, and pushing to origin. This process is no different than when dealing with GitHub hosted repositories.

Upstream Changes

C:\WCP\VisualStudioOnlineFork [master]> echo Downstream Merge >> .\README.md
C:\WCP\VisualStudioOnlineFork [master +0 ~1 -0]> echo MIT >LICENSE.md
C:\WCP\VisualStudioOnlineFork [master +1 ~1 -0 !]> git add -A
C:\WCP\VisualStudioOnlineFork [master +1 ~1 -0]> git commit -m "Added LICENSE and updated README"
[master 7f7d2ab] Added LICENSE and updated README
 2 files changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 LICENSE.md
C:\WCP\VisualStudioOnlineFork [master]> git push
Counting objects: 6, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (4/4), 368 bytes | 0 bytes/s, done.
Total 4 (delta 0), reused 0 (delta 0)
remote: Analyzing objects (4/4) (2 ms)
remote: Storing pack file and index...  done (374 ms)
To https://woodcp.visualstudio.com/DefaultCollection/_git/VisualStudioOnlineFork
   d2c3b1a..7f7d2ab  master -> master
C:\WCP\VisualStudioOnlineFork [master]>

Downstream Merge

C:\WCP\VisualStudioOnlineFork [master]> cd C:\fork\VisualStudioOnlineFork
C:\fork\VisualStudioOnlineFork [master]> git fetch upstream
remote: Microsoft (R) Visual Studio (R) Team Foundation Server
Unpacking objects: 100% (4/4), done.
From https://woodcp.visualstudio.com/DefaultCollection/_git/VisualStudioOnlineFork
   d2c3b1a..7f7d2ab  master     -> upstream/master
C:\fork\VisualStudioOnlineFork [master]> git merge master upstream/master
Updating d2c3b1a..7f7d2ab
Fast-forward
 LICENSE.md | Bin 0 -> 12 bytes
 README.md  | Bin 26 -> 64 bytes
 2 files changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 LICENSE.md
C:\fork\VisualStudioOnlineFork [master]> git push
Counting objects: 6, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (4/4), 368 bytes | 0 bytes/s, done.
Total 4 (delta 0), reused 0 (delta 0)
remote: Analyzing objects (4/4) (2 ms)
remote: Storing pack file and index...  done (496 ms)
To https://toddwood.visualstudio.com/DefaultCollection/_git/VisualStudioOnlineFork
   d2c3b1a..7f7d2ab  master -> master
C:\fork\VisualStudioOnlineFork [master]>

Conclusion

I am a big fan of GitHub but when your clients decide to use Visual Studio Online that is exactly what you do. However, this does not mean you need to abandon certain Git repository work flows and setups that are proven to work.

I have been using Visual Studio Online for the past three months without any complaints. The integration with Visual Studio 2013 is very nice and the agile management online is well done. The lack of a Fork button on Visual Studio Online is a minor inconvenience considering the process of forking repositories is still possible as I demonstrated.

Be Sociable, Share!

About Todd Wood

Solution Architect and owner of Wood Consulting Practice, LLC. C#, ASP.NET MVC, Oracle, RoR, and Linux et al rolled up into one on my Mac.
This entry was posted in Git and tagged , , . Bookmark the permalink.
  • unixscripter

    I have a question about upstream and downstream merges. I created an empty GitHiub repository, cloned an existing repo from someone else’s project following the steps in your article. Since the “forked” project is hosted at GitHub.com are my changes flowing back to the original repo or are the changes I make safely isolated from the original? I don’t want to trample on someone’s repo while I am experimenting with command-line git to GitHub synchronization.

    • Your changes are isolated to the remote you push. In my example, the forked repository is setup as the default origin and will be the target of unqualified pushes. You would need to explicitly issue a push to the upstream repository.

      Typically, you would not have push access to the upstream repository if you do not own it or were granted rights. This provides some assurance against pushing to the wrong repository.

      Hope this helps, thanks.

      • unixscripter

        Perfect. I was almost certain access privileges would prevent push access to the upstream repository but your confirmation removes any formerly lingering doubt. Thank you for the prompt response.

  • Robert Martinez

    Would something like this work if I want to work from a branch of an opens source project like Orchard CMS? I wasn’t originally sure what to do (before I found this article), so several months ago I created a clone on my local machine (say c:/orchardsource/). I then just “copied” over to a VS directory I created (say c:/vsorchard/). This is what I use for VS online. I knew this would be a problem later on, and it was because the original I cloned was version 1.8, and version 1.8.1 just came out.
    Now, I could just update the c:/orchardsource/ and use something like WinMerge to copy over new or updated files to c:/vsorchard (and then subsequently push those up to VS online), but that seems unecessary. Thanks in advance for any insight.

    • Since your repositories share a common ancestor, you should be able to just set an upstream remote in vsorchard to orchardsource. You can then fetch the upstream changes and merge into your vsorchard clone (fork).

  • Rainabba

    Thanks for the article. As I got going I learned a few things and took another route that I wanted to share if only to learn why it’s not a good way to go 🙂

    git subtree split –prefix=sourceFolderInAnyExistingProject -b anyNewBranchNameForFork
    mkdir ../someNewRepoFolder
    cd ../someNewRepoFolder
    git init –bare
    cd backToOriginalWorkingFolder
    git push ../someNewRepoFolder anyNewBranchNameForFork:master

    cd ../someNewRepoFolder
    git remote add origin YourNewRepoRemote
    git push -u origin –all
    cd ..
    rm -rf somenewRepoFolder
    git clone YournewRepoRemote someNewRepoFolder

    Sorry if that’s not clear enough, but basically, you use git subtree split to take ANY folder presently in a repo and create a branch that’s filtered to have just that folder and all the history for it. Then you create a bare repo, push the branch into it, then push that repo (without working folder) to your new repo, then either trash the folder or clone the repo into another one and BAM, you’ve forked not only an existing repo, but just one folder in it if you prefer (I had many “projects” in one repo that needed to be forked individually so this was useful for me) and history stays intact.

  • Joshua Hoffman

    Is there a convenient way to get VS to stop trying to push changes to the upstream repo?

    Ideally I’d like to maintain the ability to push upstream if I choose to (even if it has to be via git bash or another tool), but I’d like to get back the functionality where the “sync” button only pushes to my origin repo and not my upstream.

    So far the best I’ve been able to come up with is manually adding and removing the upstream (or maybe making an alias or script that does so and running it via git bash)

    EDIT: In my case, the upstream is an internal core libraries repo which I do have access rights to and may have occasion to change.

  • Ryan Jackson

    Is there a way to make repositories public?

  • Eduardo Miranda

    good article, still one of the only to talk about this. Were you able to create a pull request from the forked project into the upstream project?

  • David Elish

    Is it possible to have a GitHub upstream original and a TFS origin? There is a public GitHub project that I would like to fork for my client but maintain their fork in a Team Foundation Service Git repo without losing the “connectivity” to the original GitHub project.