There were two independent repositories with their own stories: A and B. At some point, it was decided to place the entire contents of B in A. This was done by simply copying files, i.e. in A , a single commit for this action appeared. Further, the repository A developed, in particular, the parts that used to be in B changed.

Now there is an awareness that it was not worth merging the whole thing into one repository and needs to be developed separately.

My first thought: just transfer all the parts (files) that should be in B from A. Thus, a single commit will appear again and you can live on. But I would still like to transfer the change history of these files to the repository B.

In this regard, the question: is there any mechanism that allows you to transfer commits between unrelated repositories? The option of manually copying each individual state with the corresponding description is not suggested :) I would like, conditionally, to set the range of commits from A and apply them to B.

    2 answers 2

    First of all, you need a working copy with two remote repositories. An example of obtaining such a copy:

    git init git remote add remote_a url_a git remote add remote_b url_b git fetch remote_a git fetch remote_b git checkout -b master remote_a/master 

    First, you need to highlight in A the changes in the files, which actually should be in B. This is done by the git filter-branch command, the exact command will depend on how you are going to separate the files of different repositories. Most likely it will be something like:

     git filter-branch --subdirectory-filter path/to/b <начальный коммит>..HEAD 

    Now the resulting branch remains to rebuild on B and push:

     git rebase <начальный коммит> --onto remote_b/master git push remote_b HEAD:master 

    Not tested, there may be typos.

    • Do I need to explicitly specify a range of commits? It seems like there is an option -all . PS I have not tested it yet. Tomorrow I'll try already. - αλεχολυτ
    • @alexolut with a limited range will work faster :-) - Pavel Mayorov
    • So will it be limited if the initial commit is really the initial one? - αλεχολυτ
    • @alexolut but you said that the files from B were copied to an already existing A? So, the initial commit for B inside A is not the initial commit for A. - Pavel Mayorov
    • 2
      I had to tinker a bit because of the presence of different branches and resolve conflicts during a rebase , but everything rebase out. However, some commits have been duplicated and now something like >>>>>>> Merge commit 'c99785032a9... now jumps >>>>>>> Merge commit 'c99785032a9... . What, of course, was not in the source diffs. - αλεχολυτ

    We would like, conditionally, to set a range of commits from A and apply them to B.

    In principle, this can be arranged with a combination of two teams. Get a list of all commits from and to with the git rev-list command. Then apply them with the git cherry-pick command.

     git cherry-pick `git rev-list --reverse <commit_hash_1>..<commit_hash_2>` 

    <commit_hash_1> and <commit_hash_2> should be replaced with initial and final hash hashes that define your range. We ask Git to list them in reverse order, from earlier to later. (rev-list simply outputs them to the standard stream). This is all so that git cherry-pick uses them correctly.

    The specified command must be executed within the target repository (B). It is assumed that you have previously synchronized with the source repository (A). For example:

     git fetch https://github.com/octocat/Hello-World 
    • In your opinion, you have git rebase <commit_hash_1> <commit_hash_2> --onto HEAD :) - D-side
    • I do not understand. And where is the work with different repositories? - αλεχολυτ
    • @alexolut, it is assumed that you have previously synchronized with the source repository. For example: git fetch URL/путь . - mymedia
    • Those. the target is B , and the source, therefore, A ? - αλεχολυτ
    • @alexolut, yes, exactly - mymedia