Re: Is there a way to exclude user-specified files or directories from participating in merges?

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Junio C Hamano <gitster@xxxxxxxxx> writes:

> Brent Goodrick <bgoodr@xxxxxxxxx> writes:
>
>> Suppose I create a git repo called central.git on a machine I will
>> call "central". In that central.git repo, I put these files:
>>
>>   work.sh
>>   home.sh
>>   generic.sh
>>
>> When I clone the central.git repo on to a different machine I will
>> call "work", I want this fileset to be pulled:
>>
>>   work.sh
>>   generic.sh
>>
>> But not the home.sh file.
>
> You would have one common branch and one branch per deployment.
>
> A common branch would host only common files (e.g. generic.sh file from
> your example).  Per deployment branch, e.g. home, would branch from the
> common branch (so it starts with some version of generic.sh) and may add
> its own private files (e.g. home.sh).
>
> And stick to the following two rules:
>
>  - You make edits to common files only on the common branch.
>  - You merge from common to deployment, never the other way.
>
> So at work, you would have a checkout of your work "deployment branch",
> and find needs to change things.  It is Ok to edit both work.sh and
> generic.sh (without being able to edit both, it would be hard to verify if
> the changes would work together) at this time, but don't commit the result
> in the work branch.
>
> Save the changes to work.sh away (e.g. "git diff work.sh >P.diff" and then
> "git checkout HEAD work.sh"), switch to the common branch, and commit the
> changes to the generic file.  Switch back to the deployment branch, merge
> the common branch (to pick up the changes to home.sh), reapply the changes
> specific to the deployment you saved earlier (e.g. "git apply P.diff"),
> tne commit the result.

By the way, earlier in a different thread, somebody wondered if being able
to make a commit on detached HEAD is a good thing, and this is a good
example of why it is convenient.  When I use the above "one-way merge,
never merging back" workflow in real life [*1*], I do not use a simple
"git diff work.sh >P.diff && git checkout HEAD work.sh" to save away the
tentative changes I made and verified on the deployment branch.  The above
is an oversimplified example.

For one, in real life projects, there are many files that are specific to
individual deployments, and for another, distinction between generic vs
deployment specific changes does not cleanly appear at file boundaries.

Instead, I would make a real commit, with full intention of discarding it
later.

                  T work
                 /
         ...o---o
               / 
       ...o---o common

I would go back to common branch ("git checkout common"), cherry-pick the
commit from the deployment branch ("git cherry-pick --no-commit work").
This would conflict heavily because the common branch does not have any
changes specific to the deployment branch (i.e. files that were modified
since the deployment forked from the generic, and files the deployment
added).  That is Ok.  I would use "git add -i" and editor to sift out the
deployment specific parts to discard, and commit only the parts of the
change T made that are truly generic:

                  T work
                 /
         ...o---o
               / 
       ...o---o---A common

Then I would go back to the deployment, and detach the head at commit
before the tentative commit T.  From here, I can merge the common branch
in.

                  T work
                 /
         ...o---o HEAD
               / 
       ...o---o---A common

"git merge common" would make something like this:

                  T work
                 /
         ...o---o---B HEAD
               /   /
       ...o---o---A common

I know that the remainder of the change (i.e. difference between B and T)
should be the parts that are specific to the deployment.  After reading
through the output of "git diff HEAD work" to make sure that it has all
deployment specific changes I made (and nothing that should have been in
the commit A on common), I would:

	git read-tree -m -u work && git commit

to grow the history of detached HEAD.

                  T work
                 /
         ...o---o---B---C HEAD
               /   /
       ...o---o---A common

After this step, just wrap it up with:

	git branch -f work && git checkout work

to reach the final state:

                  T
                 /
         ...o---o---B---C work
               /   /
       ...o---o---A common

The tentative commit T becomes dangling but we know "diff T C" are empty
and records the good state we verified when we made T.

This is one case I still use the plumbing "read-tree -m -u".


[Footnote]

*1* http://gitster.livejournal.com/26540.html
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]

  Powered by Linux