Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I merge changes from a branch that contains a subset of directories from another?

I'll try to keep this brief.

We have a git repository that is acting as an SVN mirror (managed by BitBucket). This repo contains every project in the company since the beginning of time and having every developer clone it is not a reasonable request (25+33GiB full clone and 15+GiB shallow) But even then, we don't need a full clone of the entire repository, just a subset of the directories within.

Using git-subtree, I managed to split out all the directories of interest and figured we could add these directories back in our local repos using git-subtree add. This process is transparent to the svn repository. This works out well and the size is much more manageable (9+6GiB full clone and 8GiB shallow). The problem is I don't know how we could take changes we make in these "partial clones" and merge them back into the master branch.

I thought we'd be able to use the usual pull requests to get them in but since the trees of the branches are different, it doesn't behave like I'd want it to (the missing directories are treated as removals). I just want to merge the changes of the cloned directories and leave the others untouched.

I don't think using a sparse checkout would help here since we still would have to clone the full repo to make it work which is exactly what I'm trying to avoid.

Is there some combination of commands I can use to make this all work?


Here's the (modified) scripts that I used to split out the directories and to checkout the directories of interest:

split_projects.sh
I used git-subtree to split and rejoin the directories and used git-replace to improve the speed of resplitting (to only process the new commits). Note that the rejoin is not committed to the main repo (I am not willing to try to commit that especially with the svn mirror).

initial_setup.sh
This is the script to prepare the local repo. To be used by Windows users, many of whom are not very experienced with git or command line tools.

checkout_projects.sh
The actual checkout script.

There's another that pulls in updates from the split subdirectories but I'm not including it here.

like image 671
Jeff Mercado Avatar asked Jan 23 '17 17:01

Jeff Mercado


People also ask

How do I merge two branches of a file?

On the Select the source and target branches for the merge operation screen: In Source branch, specify the main branch. In Target branch, specify the development branch. Click Next, and then click Finish. Click AutoMerge or merge the changes manually. After the conflicts are resolved, click Yes to save the file.

How do I merge feature1 into main branch in Git?

To bring the feature1 branch into the main branch, Git performs a three-way merge. Git takes a snapshot of three different commits to create a new one: git checkout to switch to the branch you want to merge into. This branch is typically the main branch.

How do I integrate changes from another branch?

git merge. The "merge" command is used to integrate changes from another branch. The target of this integration (i.e. the branch that receives changes) is always the currently checked out HEAD branch.. While Git can perform most integrations automatically, some changes will result in conflicts that have to be solved by the user.

What is merging in Git?

Merging takes your branch changes and implements them into the main branch. Depending on the commit history, Git performs merges two ways: fast-forward and three-way merge. Let’s examine both of these based on the branches and commit history in the following diagram.


1 Answers

If you don't want some changes merged back, do your merge --no-commit and undo those changes in the merge result before committing. For unwanted deletions, just git checkout the version you want. For unwanted change hunks, git checkout --patch.

Another option, which might wind up simpler if it's really just folding in toplevel subtrees missing from the merged branch, is to do the merge and amend it afterwards, a (git ls-tree @; git ls-tree @^1|grep ^04)|sort -usk4 | git mktree will generate the right tree easily enough, so

fixup=`(git ls-tree @; git ls-tree @^1|grep ^04)|sort -usk4|git mktree`

commit=`git show -s --pretty=%B @|git commit-tree -p @^1 -p @^2 $fixup`

git update-ref -m 'fold in missing subdirectories' @ $commit

after the merge and you're done.

like image 61
jthill Avatar answered Sep 23 '22 18:09

jthill