There\'s a special place in hell for people who hardcode absolute paths and database credentials into multiple random places in web applications. Sadly, before they go to he
Personally, if I had to do something like this and was for whatever reason prevented from refactoring credentials as I go, I'd add two more branches, ending up with an arrangement similar to the following:
master
: the original code you inherited
localcred
: branch from master, and add just the one patch that changes all the credentials to what you need locally. Treat this branch as read-only hereafter (and possibly add a hook to prevent accidental commits).
feature
: branch from master, and all fixes go here (and possibly add a hook to prevent merging with the patch in localcred)
local
: a branch (not a tag!) that will start out as a branch of localcred
, and then merge feature whenever you need to run your unit tests. All testing happens from here, but no development happens here. In addition, this branch is disposable, because you might want to rebase inside of feature
, and the fastest way to deal with the result will be to delete branch local
, branch it again from localcred
and merge feature
before running your tests. This is likely to be a common enough operation in my workflow that I'd build an alias to do it repeatedly in just a few keystrokes, but I work the hell out of the disposability of Git branches, which kind of freaks out some people who watch me, so YMMV.
When you think your fixes are ready for publication, you do your final rebase of feature
to clean up the history, dump and recreate local
for your final test, merge feature
into master
, and once that's accepted upstream, merge master
into localcred
and rebase your credential patch to the top, then dump and recreate local
and feature
and play the game all over again.
If you want to rapidly test a large set of tiny variations of code without having to commit and merge each time, checkout local
, make your changes until you're happy, commit, and immediately cherry-pick from local
into feature
, then drop and recreate local.
Does that satisfy your needs?
I would do an interactive rebase against master and move your path-name-fixup-commit to the end. Then, you can merge up to the that point. Just keep moving your special commit to the end.
You may also find the stash useful. Instead of actually committing the path name fixups you could stash them away. If try this approach you may want to check out the question on How to reverse apply a stash.
ok. this is not guaranteed to work every time but something like this can work (and in the cases it wont you will have a conflicting changes anyway that has to be resolved):
when doing merge to the master:
rebase -i master
from your branch and move the local-only change to the END of the patch chain.merge your local-branch -1:
git merge local^
This will leave you with master having all the changes on the local except for the last one.
If you have multiple local=only changes, I suggest you squash them together during rebase.
Well, because no answer so far provided a straightforward solution, I'll assume what I want to do is impossible, and add to the pile of occasionally useful solutions:
If you're always developing on the features
branch, then you can merge features
to master
, and then, in master
, git revert local
. (Where local
is the tag referencing the commit where you customized the paths, etc for your local environment.)
Now you must never merge master
into features
, because that would merge the reverse local
commit too.
In this case master
becomes sort of a deployment branch, only ever receiving merges from other branches. (Ideally, only from the features
branch.)
This goes downhill very easily, just add another developer to the workflow and things get really messy. Still can be worked around by using explicit merge strategies, but it's generally a pain.
I don't know if this would work, but:
MAKE_LOCAL
MAKE_REMOTE
git cherry-pick MAKE_REMOTE
(or use git diff
and patch
)git cherry-pick MAKE_LOCAL
(or use git diff
and patch
)I think there is an even better way of transforming files in this manner, but I can't recall (if you can find shacon's git presentation from RubyConf, and can wade through 800 slides, it's in there with some great examples).
My solution to this problem uses rebase rather than merge
Starting with a commit tree like this:
a-b-c <-- master
\
d <-- local
\
e-f-g <-- dev
$ git rebase --onto master local dev
master
V
a-b-c-e'-f'-g' <-- dev
\
d <-- local
$ git checkout master
$ git merge dev
master
V
a-b-c-e'-f'-g' <-- dev
\
d <-- local
$ git rebase --onto master master local
master
V
a-b-c-e'-f'-g' <-- dev
\
d' <-- local
$ git branch -f dev local
master
V
a-b-c-e'-f'-g'
\
d' <-- local
^
dev