Search code examples
gitgit-rebasegit-cherry-pick

Create a new Git repository from current HEAD, set it as a remote of the original, and mirror future changes to both repositories?


The current repository has commits

  A -> B -> C
            ^
            |
         HEAD

I want to create a new repository whose master branch begins at commit C (HEAD) of the current repository.

  C
  ^
  |
HEAD

Additionally, if a new commit D is added to the current repository:

  A -> B -> C -> D
                 ^
                 |
                HEAD

The new repository will become:

  C -> D
       ^
       |
      HEAD

On the next push/mirror.

Due to learning to develop software while I committed changes to the project, the repository has gone in size due to large files being added and removed through it's long history (500 commits).

Can this workflow be easily achieved in git? (Using both GitHub and GitLab)


Solution

  • What you are trying to do is close to impossible. In git, the history leading to a given commit is an inseparable part of that commit. Thus the commits denoted with C in the following two histories

      A -> B -> C
                ^
                |
             HEAD
    

    and

      C
      ^
      |
    HEAD
    

    are in fact two different commit objects, most likely having two separate hashes. The only way to achieve the desired setup would be to tweak those two different commit objects to have the same hash value, in which case you can fool git into pushing new commits based on C into different repositories with different prehistories. This can be achieved in theory but hardly in practice (if you manage to do that, then you will also be able to hack digitally signed documents or alter the bitcoin blockchain).

    An approximation of the desired flow will be to maintain two branches in your local repository corresponding to the two remotes. You will work on one of the branches, and merge it regularly into the other branch:

    old_repo_branch:      A -> B -> C ---->  D' -> E'
                                             ^     ^
                                            /     /
                                           /     /
    new_repo_branch:                C' -> D --> E
    

    You will have to push new_repo_branch to the new repository, and old_repo_branch to old repository. But such a flow will become hard to manage if you need to branch your development (since each of the parallel development streams will need to be branched and each pair of respective branches will similarly need to be kept in sync).