# how to add a (history-laden) subdirectory into a repo?

3 messages from 2019-12-13 to 2019-12-13. Participants: Robert P. J. Day, Elijah Newren, Junio C Hamano.
Thread: https://gitlist.dev/t/52446

## Robert P. J. Day, 2019-12-13 10:00

Subject: how to add a (history-laden) subdirectory into a repo?
Message-ID: <alpine.LFD.2.21.1912130447510.5127@localhost.localdomain>
URL: https://gitlist.dev/e/alpine.LFD.2.21.1912130447510.5127%40localhost.localdomain

```

  (i suspect there's an easy solution -- possibly involving
filter-branch or elijah newren's git-filter-repo, or possibly
something even simpler, so let me try to be brief.)

  i have a xilinx petalinux (vendor) repo that i started from scratch,
with a certain amount of history that i would like to hang onto --
assume the top-level structure (as created by the petalinux-create
tool) is:

  board_name/
    dir1/
    dir2/
    ... etc etc ...

and so on, and so on. that is the structure of my current repo,
totally isolated from other content.

  now, at this client site, they're using petalinux, but their
existing repository buried the petalinux project content inside a
larger build infrastructure that involves docker and other tools, so
the client's single repo has the structure:

  client_repo/
    blah1/
    blah2/
      woof1/
      woof2/
      board_name/      <---- subdir content in client repo
        dir1/
        dir2/
        ... etc etc ...

from my perspective, the ideal solution would have been for the client
to develop its build infrastructure, and include the PL project as a
submodule or subtree, as that content really is independent from the
build infrastructure but, for whatever reason, the above is all just
one honking big repo with commits to the build content intermixed with
content related to the PL project.

  i'd like to add my PL repo into that structure -- as you can see,
all my commits will be relative to the dir structure "board_name/",
while the corresponding content in the client repo will be relative to
"client_repo/blah2/woof2/board_name/".

  if submodules or subtrees are not an option, what is the easiest way
to insert my content into the appropriate subdirectory in the client
repo, while retaining my history? i'm sure there's a simple way to do
this, it just escapes me at the moment.

rday

-- 

========================================================================
Robert P. J. Day                                 Ottawa, Ontario, CANADA
                         http://crashcourse.ca

Twitter:                                       http://twitter.com/rpjday
LinkedIn:                               http://ca.linkedin.com/in/rpjday
========================================================================

```

## Elijah Newren, 2019-12-13 17:16

Subject: Re: how to add a (history-laden) subdirectory into a repo?
Message-ID: <CABPp-BEke9YSUp=DDS6jZCk0z6SR64FMv5nLCLoJDE=52d8MMg@mail.gmail.com>
URL: https://gitlist.dev/e/CABPp-BEke9YSUp%3DDDS6jZCk0z6SR64FMv5nLCLoJDE%3D52d8MMg%40mail.gmail.com
In-Reply-To: <alpine.LFD.2.21.1912130447510.5127@localhost.localdomain>

```
HI Robert,

On Fri, Dec 13, 2019 at 2:28 AM Robert P. J. Day <rpjday@crashcourse.ca> wrote:
>
>   (i suspect there's an easy solution -- possibly involving
> filter-branch or elijah newren's git-filter-repo, or possibly
> something even simpler, so let me try to be brief.)
>
>   i have a xilinx petalinux (vendor) repo that i started from scratch,
> with a certain amount of history that i would like to hang onto --
> assume the top-level structure (as created by the petalinux-create
> tool) is:
>
>   board_name/
>     dir1/
>     dir2/
>     ... etc etc ...
>
> and so on, and so on. that is the structure of my current repo,
> totally isolated from other content.
>
>   now, at this client site, they're using petalinux, but their
> existing repository buried the petalinux project content inside a
> larger build infrastructure that involves docker and other tools, so
> the client's single repo has the structure:
>
>   client_repo/
>     blah1/
>     blah2/
>       woof1/
>       woof2/
>       board_name/      <---- subdir content in client repo
>         dir1/
>         dir2/
>         ... etc etc ...
>
> from my perspective, the ideal solution would have been for the client
> to develop its build infrastructure, and include the PL project as a
> submodule or subtree, as that content really is independent from the
> build infrastructure but, for whatever reason, the above is all just
> one honking big repo with commits to the build content intermixed with
> content related to the PL project.
>
>   i'd like to add my PL repo into that structure -- as you can see,
> all my commits will be relative to the dir structure "board_name/",
> while the corresponding content in the client repo will be relative to
> "client_repo/blah2/woof2/board_name/".
>
>   if submodules or subtrees are not an option, what is the easiest way
> to insert my content into the appropriate subdirectory in the client
> repo, while retaining my history? i'm sure there's a simple way to do
> this, it just escapes me at the moment.

Hi Robert,

I'm still not quite sure what you want, but here's a few possibilities:

If you want the history of your PL repo kept the same (with everything
under "board_name/") but for the merge and subsequent commits to have
the content at "client_repo/blah2/woof2/board_name/", then you just
fetch the PL repo's history into the other and do a merge using the
subtree merge strategy.

If you want to rewrite the history of your PL repo (so that not only
new commits but history has all paths under
"client_repo/blah2/woof2/board_name/"), which will allow people to do
things like "git log -p -- client_repo/blah2/woof2/board_name/" and
see the historical commits from your PL repo, then use filter-repo's
--to-subdirectory-filter option ("git filter-repo
--to-subdirectory-filter client_repo/blah2/woof2"), and then merge the
repos together afterward. (And since the paths now line up, you won't
need to use the subtree merge strategy).  Note that I'm assuming
you'll just be merging one branch in and not pulling in tags.  If tags
of the PL repo are important and possibly conflict, you may also want
to look at the --tag-rename option to filter-repo as well.

If you not only want paths to line up but want to avoid a big merge
commit and instead weave commits together from the two repositories to
pretend they were all in the same repo all along, then I have nothing
for you.  There are so many choices and ways to "weave commits
together"; I think it'd be a cool thing to do on top of filter-repo,
but never came up with anything.  I've got a few ideas, but...they
sound like too much work and it's really not my itch to scratch.  Or
at least isn't right now.


Hope that helps,
Elijah

```

## Junio C Hamano, 2019-12-13 18:47

Subject: Re: how to add a (history-laden) subdirectory into a repo?
Message-ID: <xmqqblsckqpd.fsf@gitster-ct.c.googlers.com>
URL: https://gitlist.dev/e/xmqqblsckqpd.fsf%40gitster-ct.c.googlers.com
In-Reply-To: <alpine.LFD.2.21.1912130447510.5127@localhost.localdomain>

```
"Robert P. J. Day" <rpjday@crashcourse.ca> writes:

>   I have a xilinx petalinux (vendor) repo that i started from scratch,
> with a certain amount of history that I would like to hang onto --
> assume the top-level structure (as created by the petalinux-create
> tool) is:
>
>   board_name/
>     dir1/
>     dir2/
>     ... etc etc ...
>
> and so on, and so on. that is the structure of my current repo,
> totally isolated from other content.
>
>   Now, at this client site, they're using petalinux, but their
> existing repository buried the petalinux project content inside a
> larger build infrastructure that involves docker and other tools, so
> the client's single repo has the structure:
>
>   client_repo/
>     blah1/
>     blah2/
>       woof1/
>       woof2/
>       board_name/      <---- subdir content in client repo
>         dir1/
>         dir2/
>         ... etc etc ...
>
> ...
>   I'd like to add my PL repo into that structure -- as you can see,
> all my commits will be relative to the dir structure "board_name/",
> while the corresponding content in the client repo will be relative to
> "client_repo/blah2/woof2/board_name/".

I think that pretending your history were all touching paths with
client_repo/brah2/ prefixed to them so that the shape of the working
tree resembles with each other is the easiest part of the problem.
You could filter-branch or filter-repo your history or even create a
fast-export stream and munge paths in it before running fast-import
on the result.

A much bigger issue is what you want to record as the result of such
a merge.  Your client repository may have their own changes they
want to keep, and your repository (with paths appropriately munged
to match) would also have your changes you want to keep.  Obviously
there won't be any common ancestor between these two histories, as
they evolved independently without being aware of the other.

"git merge --allow-unrelated-histories" would give you a chance to
record the result of such a merge, but you'd need to sort the
conflict out to match your customer needs.


```
