Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
867 views
in Technique[技术] by (71.8m points)

git - Avoiding merge conflicts when merging master into per-host customized branch

I want to store all my dotfiles in git repository with separate branch for each machine. I have a problem I can't solve that blocks me from using git for that purpose. I'd like to know how other people solved it.

I'm going to have a single master branch which contains only template definitions and definitions which are supposed to be common for all branches, for example:

export EMAIL="@EMAIL@"
export SURFRAW_google_results=1000

I will replace @EMAIL@ with my correct e-mail on machine branches and commit it but SURFRAW_google_results will stay the same. For example, on work branch I'll have this:

export EMAIL="user@corp.com"
export SURFRAW_google_results=1000

Now, I decided to change SURFRAW_google_results=1000 to 10. It's supposed to be shared globally, so I first I change it on master:

export EMAIL="@EMAIL@"
export SURFRAW_google_results=10

and then on I rebase work onto master:

$ git checkout work
$ git rebase master

And now I get conflict because the line that is above the line I changed is different:

<<<<<<< a60114eea1c98d2354a07bd4fd0cdd63cba62e93
export EMAIL="@EMAIL@"
export SURFRAW_google_results=10
=======
export EMAIL="user@corp.com"
export SURFRAW_google_results=1000
>>>>>>> m

In case of bash I could quickly get away with including a machine-specific part by sourcing mechanism but how about configs that do not support including/sourcing other configs such as .fluxbox/keys or .screenrc?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Instead of modifying concurrent data directly between branches (which results in conflict as illustrated in this answer), you can considering content filter driver, using .gitattributes declaration.

smudge (image from "Customizing Git - Git Attributes", from "Pro Git book")

The idea is to manage those dotfiles in version, but with template placeholders in place of the actual values (which depends on the branch).
The generated actual dotfiles remains ignored (by the .gitignore).
That means your actual working tree does not get "dirty".

The files with the actual values can also be versioned, but with different names (so no conflicts when merging/rebasing)

The smudge script select the correct value file depending on the branch name, and generate the correct dotfile based on the dotfile template the smudge script is applied on during a git checkout.

To have a smudge acting differently per branch, I would recommend calling a script which starts by looking the name of the current branch.
See an example in my older answer "Best practice - Git + Build automation - Keeping configs separate".

#!/bin/sh
branch=$(git rev-parse --symbolic --abbrev-ref HEAD)

The OP mentions that, for the smudge script to apply on checkout, removing the index is needed. That is true, as I explained here:

the index is the middle-man for moving things from your work-tree to the object-store AND for moving things from the object-store to your work-tree.

By removing the index, you force git to restore it, which means applying any content filter driver if present.

See "git: re-checkout files after creating smudge filter".


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...