Reputation: 114847
I'm maintaining a customized version of a Ghost theme on GitHub. it's taking in a regular stream of changes from the main TryGhost/Casper repo which isn't too hard to keep track of.
There is one thing that's bothering me and that has to do with the custom-*.hbs
files in my theme. Whenever Ghost updates the post.hbs
, I must remember to merge those changes into each custom-*.hbs
template as well.
Is there a way I can tell Git that post.hbs
's changes must always be merged into multiple files on my end?
post.hbs
-> post.hbs
post.hbs
-> custom-blogger.hbs
page.hbs
-> page.hbs
page.hbs
-> custom-training.hbs
The repo, as it is currently, can be found here:
For now, I've resorted to manually diffing the changes and applying them to the related files.
Upvotes: 0
Views: 37
Reputation: 986
Short answer: No. But you can use git-merge-file
to achieve something like this:
git merge-file <current-version> <common-ancestor> <other-version>
You can use a third placeholder file to create a "common-ancestor
", that should contain the pre-merge main file:
git show HEAD~1:post.hbs > parent-post.hbs
Then running the following will make a 3-way merge:
git merge-file custom-post.hbs parent-post.hbs post.hbs
In order to automatize it you would need to do create a post-merge githook
that runs after the regular merge that recreates the common-ancestor
file and then merges the changes.
If the custom-*
files are identical to their non-custom counterpart, consider using symlinks
.
Upvotes: 1
Reputation: 489083
The short answer is no, which is a bit unfortunate.
When Git is doing a true merge—a "merge as a verb", as I like to call it—Git works with three commits: the merge base, which Git finds on its own, and two tip commits. One of the tip commits is always HEAD
, by definition, and the other is usually identified by some branch name:
o--o--X <-- you-are-here (HEAD)
/
...--o--* [merge base]
\
o--o--Y <-- other-branch
All three commits are snapshots of all files, as usual. Git performs the merge—combines the different changes since the merge base—by, in effect, running:
git diff --find-renames <hash-of-*> <hash-of-X> # what we changed
git diff --find-renames <hash-of-*> <hash-of-Y> # what they changed
Git then combs through these differences—the change-sets produced by the two diff commands—and pairs up files, so that it knows that file.ext
in the base is the same file as file.ext
in ours and/or in theirs.
If the rename-detector detects that file.ext
in the base has become newname.ext
in our commit X
, Git knows that it should combine the changes they made to file.ext
to the changes we made to newname.ext
-vs-file.ext
, storing the final result in newname.ext
. But this is strictly pairwise. Although git diff
supports several "find copies" options, there is no "find copies" option to git merge
. Furthermore, there is no "break existing pairing" option (git diff
has one, -B
with a threshold, similar to -M
for rename-finding and -C
for copy-finding): if the merge base and one tip contains a file whose path is P, that file-pair is paired for the duration of the merge. If the merge base and the other tip contains a file whose path is P, that file-pair is likewise paired.
Hence, if your merge base contains post.hbs
and both tips contain post.hbs
, the pairing is strictly post.hbs = post.hbs
.
Upvotes: 1