"brian m. carlson" [off-list ref] writes:
On 2020-06-20 at 18:21:40, Tiran Meltser wrote:
quoted
Hi,
This topic is quite common in various use cases (e.g. production
configuration vs. staging one) and there are quite a few talks about
it in the web.
Nevertheless, there is no specific solution to this problem, only
partial workarounds (including the famous merge driver “ours”).
In general, this is a hard problem. When you perform a merge, you're
asking to incorporate changes from both heads against a common merge
base. What does it mean when you want to merge two branches together
but not make any changes? Which version do you want, ours or theirs?
I believe we basically need support to apply different merge strategies
to different files.
I had similar problem a few times when I merged a long-standing branch
and, after I saw the result of merge, I was basically satisfied, except
I needed to revert a few sub-directories of the project (that gave huge
number of conflicts), to their original state, either of my current
branch, or of the branch being merged, depending on particular case. You
see, I knew exactly what I needed, yet I was not able to achieve my goal
without resorting to nasty kludges.
Normally merges are symmetric, so if you want non-symmetric behavior,
you have to define what it's supposed to be.
Yes, I'm ready to define what it's supposed to be. The problem is that
"git merge" won't let me, due to lack of support to apply different
merge strategies to different files.
As I see it, first step of improvements could be to support
git merge -- <files>
where selected strategy applies only to <files>, and the rest of files
are kept intact (effectively applying "ours" strategy to them), along
with
git merge --exclude=<files>
, to be able to exclude specific files (apply "ours" only to them)
rather than include.
[ As a side-note, please notice that after such changes, the "ours"
strategy could be deprecated (not that I think it should), as either:
git merge <branch> --
or
git merge --exclude=. <branch>
would do the trick. ]
The next step would then be to support
git merge --force -- <files>
that would force to re-merge <files> with given strategy no matter what
their current status in the index is.
Even though such support would be enough for my specific use-case, it
doesn't provide suitable way to configure the default behavior. As a
more generic solution, a new syntax for "git merge" to specify what
merge strategy to apply to what files could be designed, and then
ability to put that syntax into a file for "git merge" to pick would
solve the problem of quasi-static configuration problem. Alternatively,
even more generic .gitignore way of doing things apparently could be
re-used to some degree by adding support for .gitmerge files.
-- Sergey
On 23/06/2020 13:44, Sergey Organov wrote:
"brian m. carlson" [off-list ref] writes:
quoted
On 2020-06-20 at 18:21:40, Tiran Meltser wrote:
quoted
Hi,
This topic is quite common in various use cases (e.g. production
configuration vs. staging one) and there are quite a few talks about
it in the web.
Nevertheless, there is no specific solution to this problem, only
partial workarounds (including the famous merge driver “ours”).
In general, this is a hard problem. When you perform a merge, you're
asking to incorporate changes from both heads against a common merge
base. What does it mean when you want to merge two branches together
but not make any changes? Which version do you want, ours or theirs?
I believe we basically need support to apply different merge strategies
to different files.
I had similar problem a few times when I merged a long-standing branch
and, after I saw the result of merge, I was basically satisfied, except
I needed to revert a few sub-directories of the project (that gave huge
number of conflicts), to their original state, either of my current
branch, or of the branch being merged, depending on particular case. You
see, I knew exactly what I needed, yet I was not able to achieve my goal
without resorting to nasty kludges.
quoted
Normally merges are symmetric, so if you want non-symmetric behavior,
you have to define what it's supposed to be.
Yes, I'm ready to define what it's supposed to be. The problem is that
"git merge" won't let me, due to lack of support to apply different
merge strategies to different files.
As I see it, first step of improvements could be to support
git merge -- <files>
where selected strategy applies only to <files>, and the rest of files
are kept intact (effectively applying "ours" strategy to them),
So, essentially, for larger merges, this would be something like the
recent `--pathspec-from-file=<file>` series
https://public-inbox.org/git/7324e091ba7f48e286e6c35c7b7c40490e5c85d1.1576778515.git.gitgitgadget@gmail.com/
by Alexandr Miloslavskiy for the commands that did allow files to be
passed in via `--` lists.
It would still require merge to be extended to include just a
'partial-merge' or a 'file-merge' to clearly distinguish what is happening!
This still a symmetric merge, but with _author supplied_ pathspec
limiting, which is implicitly "ours" for the paths that are not merged.
(I don't believe that the pathspec file can have negative pathspecs, so..)
along
with
git merge --exclude=<files>
, to be able to exclude specific files (apply "ours" only to them)
rather than include.
One difficulty of .precious lists, whether embedded or local, is the
false impression that they provide any form of security to the user, so
it needs a name that make that clear.
[ As a side-note, please notice that after such changes, the "ours"
strategy could be deprecated (not that I think it should), as either:
git merge <branch> --
or
git merge --exclude=. <branch>
would do the trick. ]
The next step would then be to support
git merge --force -- <files>
that would force to re-merge <files> with given strategy no matter what
their current status in the index is.
Isn't this already the same as the restore/checkout?
Even though such support would be enough for my specific use-case, it
doesn't provide suitable way to configure the default behavior. As a
more generic solution, a new syntax for "git merge" to specify what
merge strategy to apply to what files could be designed, and then
ability to put that syntax into a file for "git merge" to pick would
solve the problem of quasi-static configuration problem. Alternatively,
even more generic .gitignore way of doing things apparently could be
re-used to some degree by adding support for .gitmerge files.
-- Sergey
Philip
On Tue, Jun 23, 2020 at 5:47 AM Sergey Organov [off-list ref] wrote:
"brian m. carlson" [off-list ref] writes:
quoted
On 2020-06-20 at 18:21:40, Tiran Meltser wrote:
quoted
Hi,
This topic is quite common in various use cases (e.g. production
configuration vs. staging one) and there are quite a few talks about
it in the web.
Nevertheless, there is no specific solution to this problem, only
partial workarounds (including the famous merge driver “ours”).
In general, this is a hard problem. When you perform a merge, you're
asking to incorporate changes from both heads against a common merge
base. What does it mean when you want to merge two branches together
but not make any changes? Which version do you want, ours or theirs?
I believe we basically need support to apply different merge strategies
to different files.
I had similar problem a few times when I merged a long-standing branch
and, after I saw the result of merge, I was basically satisfied, except
I needed to revert a few sub-directories of the project (that gave huge
number of conflicts), to their original state, either of my current
branch, or of the branch being merged, depending on particular case. You
see, I knew exactly what I needed, yet I was not able to achieve my goal
without resorting to nasty kludges.
quoted
Normally merges are symmetric, so if you want non-symmetric behavior,
you have to define what it's supposed to be.
Yes, I'm ready to define what it's supposed to be. The problem is that
"git merge" won't let me, due to lack of support to apply different
merge strategies to different files.
As I see it, first step of improvements could be to support
git merge -- <files>
where selected strategy applies only to <files>, and the rest of files
are kept intact (effectively applying "ours" strategy to them), along
with
git merge --exclude=<files>
, to be able to exclude specific files (apply "ours" only to them)
rather than include.
[ As a side-note, please notice that after such changes, the "ours"
strategy could be deprecated (not that I think it should), as either:
git merge <branch> --
or
git merge --exclude=. <branch>
would do the trick. ]
The next step would then be to support
git merge --force -- <files>
that would force to re-merge <files> with given strategy no matter what
their current status in the index is.
Even though such support would be enough for my specific use-case, it
doesn't provide suitable way to configure the default behavior. As a
more generic solution, a new syntax for "git merge" to specify what
merge strategy to apply to what files could be designed, and then
ability to put that syntax into a file for "git merge" to pick would
solve the problem of quasi-static configuration problem. Alternatively,
even more generic .gitignore way of doing things apparently could be
re-used to some degree by adding support for .gitmerge files.
I think you'd have an uphill battle to convince me that this isn't
net-negative value:
* You can just do "git merge --no-commit ...; git restore
[--source=<side>] -- <pathspec>" to do what you're talking about
above. I don't see the need to add extra functionality to merge,
especially not functionality that duplicates restore's functionality.
* The "ours" vs. "theirs" wording means you're going to have
intrinsic problems with rebases. Several users will like your choice
of what "ours" means, the other half will complain that you've got it
all wrong. I think you need to let the users decide on a case-by-case
basis, and we have a handy "git restore" command for letting them do
that already.
* The pathspec limiting is going to be a bug factory for renaming
handling. (The simplest form of which is just renaming a special path
to a non-special path or vice-versa and modifying both sides of
history.) Rename handling can already get some pretty hairy corner
cases without dumping more in the mix. I'd rather have users decide
what to do with paths that switched from being one of the special
"ours" paths to being a normal 3-way-conflict marker path. Luckily,
we already have a command that users can use to do this: git restore.
* I've run into "branch-specific" files in the wild and even
supported repositories that used them for years. In my opinion, they
are almost always nasty code smells that are artifacts from
CVS/SVN-like thinking. Although I wanted to stamp them out
immediately, there was opposition to it. However, over time, people
removed those branch-specific files from the repository (and it wasn't
just by me or at my prodding either; many were cleaned away by others
without my involvement as other folks just found better ways to handle
things over time). Giving special support to bad practices will just
enshrine them, which I'd rather avoid.
If someone wants to spend their time here, I can't stop them. Just be
aware that personally, I think it'd be a bad idea to make any
merge-recursive or merge-ort changes to support this kind of thing.
(Alternatively, if you're still convinced this is a good idea, you can
consider this email a heads up about potential problem areas that you
need to address and areas where you'll need to craft some good
arguments to win over those who are skeptical.)
Hope that helps,
Elijah