Merge back the sub-directory created from 'git filter-repo'

192 views Asked by At

Suppose I have a repository with a folder structure like this:

Base
|-dir1
|-dir2
| |-subdir1
| |-subdir2
| |-subdir3
|-dir3

I perform 'git filter-repo' on the 'dir-2' directory. Now the folder structure I have is:

Base
|-dir2
| |-subdir1
| |-subdir2
| |-subdir3

After making some changes to files present in 'dir2', I want to merge it back to the original repo from where it was filtered out and have the structure back again like this:

Base
|-dir1
|-dir2 (updated with changes)
| |-subdir1
| |-subdir2
| |-subdir3
|-dir3

How do I do this while preserving history?

1

There are 1 answers

0
torek On

How do I do this while preserving history?

There is a general answer to this question—that is, how do I do _____ while preserving history?—in Git, for anything that fills this blank, and that is: History, in Git, is commits. The commits are the history. That is all the history there is. If you have all of the commits, you have all of the history.

Hence the answer to your particular question, about merging, is simply: do the merge and make sure the result is what you like. New commits just add to the existing commits, i.e., just add more history. The old history is all still there.

The subtlety here is that how you see history depends on where you stand. If you run git log from the point just before the merge, the history you will see is the history you saw before. But if you run git log from any point at or past the merge, the history you will see may be different. Though this analogy is suspect at best, think of this as viewing a field full of crops from up close, then trying to view that same field with a large city in between you and the field full of crops. The field has not changed, you just cannot see it now because of all the tall buildings in the way, blocking your view.

When viewing history in Git, if you use git log --follow or git diff --find-renames, Git will attempt to detect renamed files. That is, we have two commits, and each commit represents a snapshot of all the files that Git knew about, at the time you (or whoever) made the commit. We place an older snapshot L on the left, and a newer snapshot R on the right, and ask Git: What changed between L and R?

Perhaps, in L, there was a file named O, which no longer exists in R. But in R, there is a file named N, which does not exist in L. If the rename detector is turned on, Git will attempt to deduce whether O and N represent the same file. (This gets into the metaphysics of identity as represented by the Grandfather's Axe or Ship of Theseus question.) If Git decides that O and N are the same file, Git will claim that O was renamed to become N, and show you the differences, if any, between those two files' contents. Otherwise, Git will claim that O was deleted and N was created.

This, again, is all that you can get in Git. It's important to know when Git will decide that a file is renamed, vs one file being deleted with another one being created, but it's also important to realize that these represent the same thing. Moreover, you can turn Git's rename detector on or off, and you can fine-tune it to some extent. There are some pitfalls around merge commits here and at present there is no simple way to work around them.

That said, as far as preserving history goes, just remember: the commits are the history. If you have all the commits, you have all the history.