Search code examples
gitrepositorygit-branchgit-pushgit-remote

Push git branch to other repository


I have the following use case:

We have a private gitlab repository and want to push to a public github repo to open source it. But the private repository and the public repository shall contain different versions of some files. E.g. different documentation, etc...

I have tried to push the opensource_branch from the private gitlab repo to the public github repo:

git push origin_github opensource_branch:master 

But the result is that all other historical commits before are also pushed (which contain documentation which shall not be public).

Any ideas how to solve this without manually copy & paste all the time?

Thanks.

PS: I have of course searched SO for similar use cases but did not find exactly this one. Every other question regarding pushing to other remotes does not have the requirement that particular historic commits shall not be visible on the remote at all.


Solution

  • Git is based on hashes. It means that the integrity is preserved along with each commit.

    A commit is linked to its parent, that's why you often see graphs of Git log with arrows pointing to the previous commit (which does not seem intuitive). In your case you may have an history like this:

    $ git log --graph --oneline
    * f329c58 Fix (HEAD -> master)
    * 9d13dc2 Another fix 
    * 5641ac5 Spelling
    * 978e43c Remove private documentation 
    * 4837aab Fix code
    ...
    * 1bcd23a Initial commit
    

    What you want to push on the remote repository is only from 978e43c. Unfortunately this commit has a parent which is 4837aab. You cannot hide it neither tell Git to not push all the history before.

    Solution 1: Rebase on an orphan branch

    One solution is to make the commit 978e43c an orphan, said differently: with no parent.

    git checkout --orphan public
    git rm -rf . # Clear the working directory
    git commit --allow-empty -m "Initial commit"
    git rebase master..978e43c 
    

    Then you will have a whole new branch which does not include your private documentation.

    This solution works but it has several drawback:

    Solution 2: Alter history with git filter-branch

    You can simply remove your sensitive documentation from the whole history with:

    export PRIVATE ./documentation/private-api
    
    git filter-branch -f \
        --prune-empty \
        --tag-name-filter cat \
        --tree-filter 'rm -rf $PRIVATE' \
        -- --all