Monday, February 10, 2020

Working with different remotes in git

One of the things that is typical when working with gitlab/github is work with different git remotes.

This is sometimes because you don't have commit access to the original repository so you fork it into your own repository and work over there, but you still want to have the original repository around so you can rebase your changes over it.

In this blog we will see how to do that with the okular repository.

First off, we start by cloning the original repository

Since we don't know the URL by memory, we go to https://invent.kde.org/kde/okular/ and press the Clone button to get a hint, if we have commit access we can use both urls, otherwise we have to use the https one, for the sake of this let's assume we do not have commit access.


$ git clone https://invent.kde.org/kde/okular.git
$ cd okular


Ok, at this point we have clone the upstream Okular repository, we can see we only have one remote, called origin


$ git remote -v
origin https://invent.kde.org/kde/okular.git (fetch)
origin https://invent.kde.org/kde/okular.git (push)


Now we want to do some fixes, since we can't commit into the main repository, we need to fork, for that we press the fork button in https://invent.kde.org/kde/okular/. Once done we end up in the fork of Okular under our name, e.g. https://invent.kde.org/aacid/okular.

Now what we want is to add our remote to the existing one, so we press the blue button (here we use the git@ one since we can always commit to our fork)


$ git remote add aacid_fork git@invent.kde.org:aacid/okular.git
$ git remote -v
aacid_fork git@invent.kde.org:aacid/okular.git (fetch)
aacid_fork git@invent.kde.org:aacid/okular.git (push)
origin https://invent.kde.org/kde/okular.git (fetch)
origin https://invent.kde.org/kde/okular.git (push)


So now we have a remote called aacid_fork that points to url fork, aacid_fork is the name i chose because it's easy to remember, but we could have used any name we wanted there.

Now there's several things one may want to do

Do changes in master and push them to your fork

This is really not the recommended way but since it's what i do and it'll explain how to push from one branch name to another i'll explain it.

After doing the changes and doing the typical git commit now we have to push the changes to our aacid_fork, so we do

git push aacid_fork master:adding_since_to_function

What this does is push the local branch master to the branch named adding_since_to_function of the aacid_fork remote

Create a branch and then push that to your fork

This is what you should be doing, so what you should do is

git branch adding_since_to_function

and then change to work on that branch

git switch adding_since_to_function

After doing the changes and doing the typical git commit now we have to push the changes to our aacid_fork, so we do

git push aacid_fork adding_since_to_function

What this does is push the local branch adding_since_to_function to a branch with the same name of the aacid_fork


Get a branch from someone else's remote and push to it


Sometimes some people say "hey let's work on my branch together", so you need to push not to origin, not to your fork but to someone else's fork.

Let's say you want to work on joliveira's gsoc2019_numberFormat branch, so you would need to add his remote


$ git remote add joliveira_fork git@invent.kde.org:joliveira/okular.git
$ git remote -v
aacid_fork git@invent.kde.org:aacid/okular.git (fetch)
aacid_fork git@invent.kde.org:aacid/okular.git (push)
joliveira_fork git@invent.kde.org:joliveira/okular.git (fetch)
joliveira_fork git@invent.kde.org:joliveira/okular.git (push)
origin https://invent.kde.org/kde/okular.git (fetch)
origin https://invent.kde.org/kde/okular.git (push)


Then we would need to tell git, hey listen, please go and read the branches that remote i just added has

git fetch joliveira_fork

Next we have to tell git to actually give us the gsoc2019_numberFormat branch, there's lots of ways to do that, one that works is

git checkout --track joliveira_fork/gsoc2019_numberFormat

This will create a local gsoc2019_numberFormat from the contents of the remote branch joliveira_fork/gsoc2019_numberFormat and that also "tracks" it, that means that if someone else does changes to it and you do git pull --rebase while on your local gsoc2019_numberFormat, you'll get them.

After doing the changes and doing the typical git commit now we have to push the changes to the joliveira_fork, so we do

git push joliveira_fork gsoc2019_numberFormat


What you don't want to do

Don't push to the master branch of your remote, it's weird, some people do, but it's note really recommended.

Things to remember

A git remote is another repository, it just so happens that it has "similar" code, but it's a fork, so you can push to it, checkout branches from it, etc.

Every time you want to get changes from a remote, remember to git fetch remote_name otherwise you're still on the "old" snapshot form your last fetch.

When git pushing the syntax is git push remote_name local_branch_name:remote_branch_name

Bonus track: Using git mr

As shown in my previous blog post you can use git mr to easy download the code of a mr. Let's use as example Okular's MR #20 https://invent.kde.org/kde/okular/merge_requests/20.

You can simply do git mr 20 and it will create a local branch named mr/20 with the contents of that MR. Unfortunately, if you want to commit changes to it, you still need to use the original remote and branch name name, so if you do some changes, after the git commit you should do

git push joliveira_fork mr/20:gsoc2019_percentFormat

2 comments:

elvis said...

Nice write-up!

One comment: After the git branch adding_since_to_function
step in the instructions above, you never check out that branch I think? So maybe add a git checkout adding_since_to_function step below it to make it more clear, or change the existing step into git checkout -b adding_since_to_function which creates and checks out the branch in one go.

Albert Astals Cid said...

I'll add the git switch command