Search code examples
gitversion-controlrepository

Pull and push multiple branches efficiently


We are moving from bitbucket to azure in our team. But while the azure stuff are being set up properly, we want to keep our repositories in both of them, and updating them to be as up to date as possible. I'm the one responsible for it.

Other team members are only using the bitbucket, pulling, pushing, switching branches, all that stuff. We probably have at least 30 branches there, old and new. I didn't want them to do complex stuff (since even managing 3 or more branches takes their time more than it should). So I update the azure one myself.

I've added two more remotes to my git configs, so I have 3 remotes now:

  1. origin: Fetch and push using bitbucket URL
  2. azure: Fetch and push using azure URL
  3. all: Fetch using bitbucket URL, push using both both azure and bitbucket URLs

Here's the output of the git remote -v command (minus the actual URLs):

all     https://bitbucket/repo.git (fetch)
all     https://bitbucket/repo.git (push)
all     https://azure/repo (push)
azure   https://azure/repo (fetch)
azure   https://azure/repo (push)
origin  https://bitbucket/repo.git (fetch)
origin  https://bitbucket/repo.git (push)

I wrote a PowerShell script to fetch the branches (git fetch then git branch -a) and find the ones starting with origin/, then iterate through them, git checkout then git pull then git push all for each of them. This does the job, I run the script once or twice per day to make sure the azure repo is up to date with bitbucket (since we only commit in the bitbucket repository for now, pushing to azure is enough). Feel free to judge the setup and criticize it, I'm open to feedback :D

However, the problem is that this script is slow. It's a mono-repo (not my choice) so we have about 10 or so .NET projects in it, with at least 30 branches. Individually checking out each of them (and waiting for the file structure to be remade by git, because the project is somewhat big and some branches are 1000 commits behind and are basically there only for archiving reasons) and pulling then pushing takes about 10 or 15 minutes. I can manually check each branch and only sync the ones that are active, but these branches change overtime and it's not a perfect solution.

Is there a way to do what I want (updating all branches in azure from bitbucket) without actually checking out in each of them? I know git already tracks all of them and doesn't need to checkout to see the changes from remote (unless it does need and I'm wrong), so maybe there is a way to use that information. I remember that I saw something, some script that would do something on multiple branches without actually checking out to them, but I couldn't find it and I don't remember the details very well.

Thanks in advance :)


Solution

  • You don't need to check out branches to be able to push them. You can push the remote-tracking branch from one remote to a different remote. You don't even need a branch at all locally, you can push any commit-ish.

    git push azure origin/branch1:refs/heads/branch1 origin/branch2:refs/heads/branch2
    

    But you might be better off looking into the --mirror options to git clone and git push. That way you can easily keep 2 repositories fully in sync:

    git clone --mirror your-bitbucket-repo bitbucket-mirror.git
    cd bitbucket-mirror.git
    git remote add azure your-azure-repo
    git fetch origin
    git push --mirror azure