Skip to content

Git and Github: keeping a feature branch updated with upstream?

Git and github, you gotta love them for managing and contributing to (FLOSS) projects.

Contributing to a Github hosted project becomes very easy. Fork the project to your personal Github account, clone your fork locally, create a feature branch, make some patch, commit, push back to your personal Github account, and issue a pull request from your feature branch to the upstream (master) branch.


git clone -o svg git@github.com:sergevanginderachter/ansible.git
cd ansible
git remote add upstream git://github.com/ansible/ansible.git
git checkout -b user-non-unique
vi library/user
git add library user
git commit -m "Add nonunique option to user module, translating to the -o/--non-unique option to useradd and usermod."
git push --set-upstream svg user-non-unique
[go to github and issue the pull request]

Now, imagine upstream (1) doesn’t approve your commit and asks for a further tweak and (2) you need to pull in newer changes (upstream changes that were committed after you created your feature branch.)

How do we keep this feature branch up to date? Merging the newest upstream commits is easy, but you want to avoid creating a merge commit, as that won’t be appreciated when pushed to upstream: you are then effectively re-committing upstream changes, and those upstream commits will get a new hash (as they get a new parent). This is especially important, as those merged commits would be reflected in your Github pull request when you push those updates to your personal github feature branch (even if you do that after you issued the pull request.)

That’s why we need to rebase instead of merging:


git co devel #devel is ansible's HEAD aka "master" branch
git pull --rebase upstream devel
git co user-non-unique
git rebase devel

Both the rebase option and rebase command to git will keep your tree clean, and avoid having merge commits.
But keep in mind that those areyour first commits (with whom you issued your first pull request) that are being rebased, and which now have a new commit hash, which is different from the original hashes that are still in your remote github repo branch.

Now, pushing those updates out to your personal Github feature branch will fail here, as both branches differ: the local branch tree and the remote branch tree are “out of sync”, because of those different commit hashes. Git will tell you to first git pull --rebase, then push again, but this won’t be a simple fast-forward push, as your history got rewritten. Don’t do that!

The problem here is that you would again fetch your first changed commits as they were originally, and those will get merged on top of your local branch. Because of the out of sync state, this pull does not apply cleanly. You’ll get a b0rken history where your commits appear two times. When you would push all of this to your github feature branch, those changes will get reflected on the original pull request, which will get very, very ugly.

AFAIK, there is actually no totally clean solution to this. The best solution I found is to force push your local branch to your github branch (actually forcing a non-fast-orward update):

As per git-push(1):

Update the origin repository’s remote branch with local branch, allowing non-fast-forward updates. This can leave unreferenced commits dangling in the origin repository.

So don’t pull, just force push like this:

git push svg +user-non-unique

This will actually plainly overwrite your remote branch, with everything in your local branch. The commits which are in the remote stream (and caused the failure) will remain there, but will be dangling commit, which would eventually get deleted by git-gc(1). No big deal.

As I said, this is AFAICS the cleanest solution. The downside of this, is that your PR will be updated with those newest commits, which will get a later date, and could appear out of sync in the comment history of the PR. No big problem, but could potentially be confusing.

bash redirection target gets funky

Can anybody explain me how this funky behaviour in bash works?

find /root  >output 2>error 3

Yes, that’s just “error” followed by a space followed by “3″.

serge@goldorak:~/tmp$ ls -l
total 8
-rw-rw-r-- 1 serge serge 71 Aug 30 13:57 error 3
-rw-rw-r-- 1 serge serge 6 Aug 30 13:57 output
serge@goldorak:~/tmp$

Lets create a file with a space in it:

serge@goldorak:~/tmp$ touch "test 1"
serge@goldorak:~/tmp$ ls -l
total 8
-rw-rw-r-- 1 serge serge 71 Aug 30 13:57 error 3
-rw-rw-r-- 1 serge serge 6 Aug 30 13:57 output
-rw-rw-r-- 1 serge serge 0 Aug 30 13:58 test 1
serge@goldorak:~/tmp$

using bash completion I get:

serge@goldorak:~/tmp$ ls -l test\ 1
-rw-rw-r-- 1 serge serge 0 Aug 30 13:58 test 1
serge@goldorak:~/tmp$ ls -l error 3
-rw-rw-r-- 1 serge serge 71 Aug 30 13:57 error 3
serge@goldorak:~/tmp$

It seems the space in “error 3″ is not a space but some other char?

Linus Torvalds on Ubuntu

Quote from Linus Torvalds:
“and some kernel people tend to dismiss Ubuntu, but I really think that Ubuntu has generally had the right approach, and been very user-centric”

The Linux-Training Project: Linux Training v2 released

As announced in February new versions of the Linux training courses were being (re-)written by Paul.

I’m pleased to announce that v2 was merged in the master branch on github.

I you want to test it or just check it out:


git clone git://github.com/linuxtraining/lt.git
cd lt
git submodule init
git submodule update
./make.sh
./make.sh build fundamentals

Feedback is welcome, by mail at contributors@linux-training.be or via a github issue.

If you prefer to just download the latest books in PDF format, check out the download page. These are nightly builds from the master branch.

The Linux-Training Project: New Books

You may have noticed that since February 2011 there have been no updates to the free pdf’s. That is because we have been redesigning the docbook source code to accommodate smaller books (we call them minibooks). This mandates a rewrite of the build system and a refitting of the .xml files and directories. This is all being done in the git experimental branch.

We take the minibook redesign also as an opportunity to rewrite/improve the content of each subject. Making this a time consuming process. The good news is that some minibooks should be coming online soon (say July 2011).  We plan to finish at least the Linux Fundamentals (big)book by the end of July (it will consist of six or seven minibooks).

 

Modern times revisited

Ge moet u voorstellen dat de muziekindustrie gewoon een nest bedrijven zijn die jarenlang op een berg geld gezeten hebben, waar een hoop managers het steeds heel goed hadden, en waar de vakbonden geen klagen hadden. Nu moeten die bedrijven plots allemaal extra hard beginnen werken voor hun geld, en is een reorganistaie niet mogelijk of minstens extreem moeilijk wegens redenen die eigen zijn aan de parabel van de tien aapjes en de menselijke natuur die tegen verandering is.

En zo zijn er een hoop bedrijven. Truvo aka. De Gouden Gids is daar nog een goed voorbeeld van.

Geekdinner.be 1103

A new Geekdinner was announced.
This geekdinner will be held at De Gekroonde Hoofden in Ghent on the 31 March 2011

More info at geekdinner.be

The Linux-Training Project: Updated make script and split linux-training and datanet

Some recent changes.

I updated the make script to be a little more decent. (A little less clumsy actually.)

The LT project contained until now both the linux-training books, but also “Datacommunicatie en Netwerken” (in short, Datanet) which is a Dutch introductory course  about data communication and basic networking. We split both projects into two separate repositories: next to https://github.com/linuxtraining/lt you can also now check out https://github.com/linuxtraining/datanet.

For now the changes are not in the master branch yet, but those will be merged in the coming days.

The Linux-Training Project: Main git repository moved to Github

Just moved the main git repository from gitorious to Github:

https://github.com/linuxtraining

You might want to update your remotes!

SSH RemoteCommand over netcat hopping, or not.

Patrick Debois‘ article on Chaining SSH tunnels inspired me to effectively start using this technique.

At first my use case was pretty simple. It wasn’t the host I needed to connect to which behind a firewall, but, as it turned out, I was.

I’ve got a box at home listening on a high port, as my provider is blocking the low <1024 ports, Which is a problem when I'm on a network which only allows outbound SSH connections on port 22. It's easy to hop around by first connecting to another server on regular port 22, but automating that with Patrick's proxycommand-plus-netcat trick proved to be handy in this situation, too.

I could easily add an entry to .ssh/config to manage this specific situation.

Now, the typical firewalled networks I need to use, I often work on them either by being on its premises, or remotely. When I need to connect remotely, especially for a longer period, I can often use a dedicated VPN for that, but very often I just want quickly check something on one host, and entering the network not by launching a full-blown VPN stack, but hopping through a SSH gateway, tends to be the preferred solution.

Normally, you then need separate .ssh/config entries for each host. And then you need a separate .ssh/config entry for each host using a specific ProxyCommand.

But this doesn’t scale well. One would need to manage redundant information. I don’t want to configure .ssh/config entries for each server separately to be reached from within its own LAN and remotely through SSH hopping.

I didn’t find a way to handle this with a config in .ssh/config only, but adding following little (Bash) function to my environment lets me use an extra ssh command which lets me use the same .ssh/config entries for both situations:

ssh-via () { proxy=$1 ; shift ; ssh -o Proxycommand="ssh $proxy nc %h %p" $* ; }

Just use ssh-via instead of plain ssh, and let the first parameter be the name of the .ssh/config entry for the gateway you need to use.

Analytics Plugin created by Web Hosting