Git Branches for Multi-root Projects

Sometimes there is a need to have multiple Git repositories within a single project. Since long ago IntelliJ IDEA is able to execute many Git operations on all roots at once: Commit, Update Project, Push. Now multi-repository support has come to branches.

In IntelliJ IDEA 11.1 we have implemented two different approaches for multi-root branches.

Most people who use multi-root setup probably have a single repository for project development and several repositories for libraries. They may be included as submodules or just as nested roots, it doesn’t matter for now. For these everything is simple. When you invoke Git Branches popup, you see all branches in the current repository. Other repositories are accessible from the popup as sub-popups with all branches listed there for each repository, with all usual branch actions available for them.

What is the current repository? If you have explicitly selected a file or folder in the Project View or elsewhere, we take the root under which the file is located. Otherwise (if you clicked on the status bar widget or from the main menu) we take the root of the file currently open in the editor.

Synchronous branch control

There is also another case: when users have several repositories in one project that are connected. We at Jetbrains have a configuration like this in one of our projects. There are 3 repositories in a single project, and these repositories are controlled synchronously, i.e. we commit, push and apply other operations to all 3 repositories at once. For such projects IntelliJ IDEA allows to control branches synchronously. It means performing all branch operations on several repositories simultaneously, as it would be a single repository.

When you invoke Git Branches for the first time, IDEA looks at the repositories registered in the project, and if they all are on branches with same names, proposes to control branches synchronously.

If you don’t need it, you may disable it right away or later in the Settings | Version Control | Git | Control branches from different roots synchronously.

If the setting is enabled, all operations on Git branches will be executed for all repositories at once. On the root level of Git Branches popup there will be listed only those local and remote branches which are common for all repositories in the project. Creating new branch from the popup will create it on all repositories, checking out a branch will checkout it on all repositories, etc. This applies to all actions including checkout, merge and delete. Compare just shows the standard dialog with additional selector to choose the root.

You may still control branches individually for each root by using repository selector in the popup. If you happen to checkout a branch only on one of the roots, you’ll get the warning that branches have diverged. Of course, you won’t get this warning if you have disabled synchronous branch control.

Rollback

There is one more nice feature for synchronous branch management. If you decided to checkout a branch on several roots, and checkout failed for some of them, but has already succeeded for others, you’re in the situation when branches diverge: for example, you are on master in one repository and on feature branch in the other.

To prevent this, the IDE offers to rollback successful checkout. Rollback checkout means just checkout back to the previous branch.

Rollback is offered for checkout, merge and other branch actions.

That’s all about Git branches for today.

We are looking forward for your feedback about the Git branch control interface in IntelliJ IDEA. Your suggestions are welcome. Please submit bug reports directly to our issue tracker.

This entry was posted in New Features and tagged , , . Bookmark the permalink.

17 Responses to Git Branches for Multi-root Projects

  1. Geoffrey De Smet says:

    Very nice, this feature will make me more efficient.
    Will this issue also fix the issue that “Open Github URL in browser” of a selected file does not work for multi-root git projects ( http://youtrack.jetbrains.com/issue/IDEA-67488 )?

  2. Kirill Likhodedov says:

    @Geoffrey
    Unfortunately, this is a separate issue, it will be fixed later.

  3. Gordon Tyler says:

    Synchronous branch control is great! I was wishing for something like that just the other day. :)

  4. Xav says:

    Will this feature be available for Mercurial also ?

  5. Kirill Likhodedov says:

    @Xav
    We plan to implement a similar interface for Mercurial, but not immediately.

  6. Xav says:

    @Kirill
    It is planned for 12 ?

  7. Kirill Likhodedov says:

    @Xav
    No, unfortunately, such interface for Mercurial is not planned for IntelliJ IDEA 12.

  8. Peter K says:

    Is it possible to save this flag to default to ON when all the repositories are initially checked out from master ??

  9. Kirill Likhodedov says:

    @Peter K
    This is already done. If you haven’t touched the flag manually, when you invoke Git | Branches the first time, it analyzes current branches of your repositories and sets itself to ON, if they all are on the same branch.

  10. Nishant says:

    Is this feature available on webstorm?

  11. Bojan says:

    Is there any specific reason why new branches can be created simultaneously in multiple repositories only when they are all on the same branch name? And than branches are being created on all repos, even those in which modules I didn’t do any changes.

    Am I doing something wrong and there is a way to make new branches only in repositories that have new changes or this is not a possibility yet? If so, is there a plan to implement this option in the future?

    • Kirill Likhodedov says:

      Currently IntelliJ IDEA supports two common workflows: all repositories are independent, and all repositories are synchronised.
      We will probably implement the possibility to switch to some common branch in all repositories even if they have diverged (i.e. are on different branches).

      But synchronous operations with only a subgroup of repositories is not supported, and we are not sure if it is much needed. Could you please share your use case: why do you need to switch branches only in a subset of repositories? do you have a fixed subset of repositories you wish to “synchronize”, or this set is always different?

      • Gustavo Vilera says:

        Hi Kirill,

        I’ll explain you my user-case, as I also would like to have the feature requested by Bojan.

        So… right now, I have a AS3 project with over 10 modules inside… some of the modules are libraries developed my me, others are Applications that partially implement the other modules.

        Let’s say I have 3 App (1 for Web, 1 for smart phones, 1 for Tablets) My other 17 or so modules (in-house developed libraries) are used in the compilation of this 3 Apps, some of them are CORE for all 3 others are exclusive for 1 or 2.

        Some of my 17 in-house developed modules are dependant on another of this modules… So I’ll have the case where Web-App includes ModuleTablets1 which requieres ModuleMobile7 which requieres ModuleCore1.

        NOW!!!… And here is where the magic begins… each of this libraries/modules have their own GIT. The same as the 3 App modules also have.

        So now you start having the picture… When I’m working on an issue that addresses the Tablets, I need to do changes on different modules… and finally I want to commit this changes.

        As it is right now, I have to do this:

        Since I don’t know at the beginning which are all the modules I need to touch until I fix the BUG or I clear a HOT -FIX… I just create a new “Changelist” where I’ll be able to see all changes.
        After I’m finished… I go to my newly created issue-specific “changelist” and see all the modules/repos I touched and go manually to each of them (They are usually at the “dev” branch at this point since I encourage and implement the use of the “Git-flow”) and create a new branch called after the JIRA ID of the issue “BJF-121″ on each of them and then commit to them the changes, just before I merge it back to “dev” to start over again.

        After I do this… I wish intelliJ could not only implement the “git-flow”, but most importantly that it would create a new branch on the touched selected repos (or at least the selected ones from my changelist) with the specific issue name, let me comment them all at ones and handle the necessary “git-flow” steps for me to be ready again to continue.

        Also…. Last but DEFINITELY not less important…. (I don’t even know if I should adress this to you guys or to GIT people directly :) But since you are the Amazing tool we use at the office… ;) )
        I would like that my App repo would somehow pass or commit the states (commit-id) of ALL the repos of the modules (the repos of the repos of the repos of my module ;)) at the time that I pull/push my app commit.

        The issue is obvious, we have core libraries/modules and App modules that are being compiled with together and we don’t know by just pulling one of the repos which changes are required for which change in this dependencies.

        BTW… Any ideas or proposals for a different Workflow are also VERY welcome! If you handle this “Inception” of git repos in a successful way, I would be more than glad to know how!! :D

        • Kirill Likhodedov says:

          Your workflow looks valid. Let me summarize it in a feature request: http://youtrack.jetbrains.com/issue/IDEA-126654 “Make Git branch operations context aware”. Feel free to comment there if you feel that you need something more or different.

          As about “connecting” repositories – you may want to try Git submodules. They are far from perfect and have many drawbacks, but may suit you. Be warned though that IntelliJ IDEA doesn’t support submodules yet. We plan to fix it in the next release, but you may have problems when using submodules in IDEA 13.1 or previous versions.

  12. Maciej M says:

    Use subtree instead of submodule, git submodules sucks

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">