4 minute read

We left off in Part 2 having our Git repository cloned into the home directory on two separate workstations. Both of these workstations are on the Linux branch and I’ve added some files. Remember that I’m using the master branch to contain all of the files/configurations that are shared between Windows and Linux.

What happens when we want to introduce changes from our Linux workstations to our Windows workstations? Certainly you could just carefully look at your diff, checkout master, and make the identical changes, but Git offers us some tools for editing history that make this even easier.

Moving a single commit into master

Assume we’ve been using our Windows and Linux branches and committing in changes. Right now my git history looks something like the following graph:

git log
* c98ec2b - (37 seconds ago) Add PowerShell profile - Alex Doe (origin/windows, windows)
| * 05bfbab - (14 minutes ago) Add another alias - Alex Doe (origin/linux, linux)
| * 11c0138 - (27 hours ago) Add SSH configuration - Alex Doe
| * e2dbae4 - (27 hours ago) Add useful git alias - Alex Doe
|/
* 443e495 - (29 hours ago) Add .gitconfig - Alex Doe (HEAD -> master, origin/master)
* 7d87207 - (31 hours ago) Add .gitignore - Alex Doe

Now that Windows has OpenSSH support, it probably makes sense to add our SSH configuration file into master so it can be shared between our Windows and Linux workstations. Basically what we want to do is move the commit 11c0138 into master, and then rebase our windows and linux branches on top of the new master. To do this, we’re going to use a cherry-pick.

DO NOT perform any of these commands in your real home directory. The working directory changes will almost certinaly break something. All of these commands should be run in your separate dedicated “working” copy of the repository.

Before we cherry-pick we need to checkout our master branch where we want the change to go. Once we’re there we run cherry-pick specifying the commit that we want to bring into our branch.

git checkout master
git cherry-pick 11c0138
git log
* b405b79 - (27 hours ago) Add SSH configuration - Alex Doe (HEAD -> master)
| * c98ec2b - (13 minutes ago) Add PowerShell profile - Alex Doe (origin/windows, windows)
|/
| * 05bfbab - (26 minutes ago) Add another alias - Alex Doe (origin/linux, linux)
| * 11c0138 - (27 hours ago) Add SSH configuration - Alex Doe
| * e2dbae4 - (27 hours ago) Add useful git alias - Alex Doe
|/
* 443e495 - (29 hours ago) Add .gitconfig - Alex Doe (origin/master)
* 7d87207 - (31 hours ago) Add .gitignore - Alex Doe

Voila! Now we have our commit from the middle of the Linux branch included in our master branch.

Rebasing other branches on master

The final thing we need to do is rebase our Windows and Linux branches on the master branch so they both properly inherit the new changes. That should be as simple as running these commands:

git rebase master windows
git rebase master linux

Now our history should look like the following graph:

git log
* 7f138b1 - (16 hours ago) Add another alias - Alex Doe (HEAD -> linux)
* 554d880 - (2 days ago) Add useful git alias - Alex Doe
| * 7b4fa32 - (16 hours ago) Add PowerShell profile - Alex Doe (windows)
|/
* b405b79 - (2 days ago) Add SSH configuration - Alex Doe (master)
| * c98ec2b - (16 hours ago) Add PowerShell profile - Alex Doe (origin/windows)
|/
| * 05bfbab - (16 hours ago) Add another alias - Alex Doe (origin/linux)
| * 11c0138 - (2 days ago) Add SSH configuration - Alex Doe
| * e2dbae4 - (2 days ago) Add useful git alias - Alex Doe
|/
* 443e495 - (2 days ago) Add .gitconfig - Alex Doe (origin/master)
* 7d87207 - (2 days ago) Add .gitignore - Alex Doe

Notice that all of the branches from origin are still behind and inheriting from the old history. We can force push them up and then pull them down to our other machines easily now. The final history looks like this:

git push --all --force-with-lease
git log
* 7f138b1 - (16 hours ago) Add another alias - Alex Doe (HEAD -> linux, origin/linux)
* 554d880 - (2 days ago) Add useful git alias - Alex Doe
| * 7b4fa32 - (16 hours ago) Add PowerShell profile - Alex Doe (origin/windows, windows)
|/
* b405b79 - (2 days ago) Add SSH configuration - Alex Doe (origin/master, master)
* 443e495 - (2 days ago) Add .gitconfig - Alex Doe
* 7d87207 - (2 days ago) Add .gitignore - Alex Doe

Conclusion

The greatest benefit to tracking your various home directories in Git is the ability to control inheritence of information. The rebase function is incredibly powerful here and lets you introduce global changes across all of your workstations very easily.

You can continue the branching concept to add multiple layers. The “linux” branch becomes “all of my normal configurations plus any Linux-specific configuration”. The “linux-work” branch becomes “all of my normal Linux configurations, plus any work-specific configuration”.

Once you start tracking things this way it becomes really easy to fix errors or make tweaks upstream. Want to tweak an alias you’ve been using for years that is on all of your workstations? Just update master, rebase, and pull on all of your workstations.