Having a private branch of a public repo on GitHub? - github

I have a public PHP project in a GitHub repo, which contains just one branch (master).
I want to have a separate branch/fork that is private for me (I have paid for private GitHub repos). I would like to be able to merge changes from the private branch/fork to the public repo, and vice versa.
With that in mind, here are my questions:
Can I have a private branch on a public repo?
Can I fork my own public repo into my own private branch/fork?
If both of the above are possible, which is the best way forward? If neither, how should I proceed?

Duplicate your repo.
Make the duplicated repo a private one on GitHub.
Clone the private repo to your machine
Add a remote to your public repo (git remote add public git#github.com:...)
Push branches with commits intended for your public repo to that new public remote. (make sure you don't accidentally commit private-only code)
You can bring in changes to your public repo using 'git fetch public' and then merge them locally and push to your private repo (origin remote).

Is it possible to have a private branch on a public repo?
On GitHub, your repository is either public or private; you cannot selectively "privatize" just a branch.
Can I fork my own public repo into my own private branch/fork?
You can clone your public repo to your local machine, branch as needed, and simply not push your "private" branches upstream (by specifying which branch to push to origin: git push origin master or git push origin branch-i-want-to-be-public:master).
Which is the best way forward/how should I proceed?
In order to take advantage of GitHub for both your public and private development, I would suggest forking your public branch within GitHub, changing the settings of the new fork to "Private", and then cloning the private version down to your local machine. When you're ready to make changes public, push everything up to your private fork on GitHub and then use pull requests to selectively copy branches to the public repo.
To make a repository private on GitHub, you must have an upgraded (paid) account. If you're only rocking the free account, you can still use the first process I suggested — clone public to local machine, branch, and push specific "public" branches to origin — without needing a private repo.
If you have a paid GitHub account, or are using another service that offers public and private forks and pull requests (such as BitBucket), then you can use either of the above approaches to make your code public.

There is another solution which I find better as it doesn't result in duplicate repos on the same machine.
Make a branch with the stuff you want private.
Make a new repo on GitHub, set it to private.
Add new GitHub repo as a second remote to your repo on your machine.
Push private branch to second remote.
End result is 1 repository with 2 remotes. 1 public, 1 private.
Just need to be careful about which you push to so name accordingly.

1.) Is it possible to have a private branch on a public repo
From what I know, no.
2.) Can I fork my own public repo into my own private branch
No, you can't fork a full repo (1-n branches) into a single branch. Well actually you could, if you just fork the one branch of the full repo. Just add it as a remote or start from a clone.
You might also be interested in Sparse checkouts.
3.) If both the above the are possible which is the best way forward
n/a
4.) If neither are possible how should I proceed?
n/a

To create private branch (downstream) of a public repository (upstream):
Initialize repository
$ git init private-repo
$ cd private-repo
Add remotes
$ git remote add upstream git#github.com:<username>/public-repo.git
$ git remote add origin git#github.com:<username>/private-repo.git
$ git remote --verbose
Initial commit
$ git commit --allow-empty --message "Initial commit"
$ git push --set-upstream origin master
Create development branch
$ git checkout -b develop
$ git push --set-upstream origin develop
$ git branch --all
Merge upstream into development branch
$ git fetch upstream master
$ git merge --allow-unrelated-histories upstream/master
$ git push
Some changes on repository...
# Do some changes...
$ git add .
$ git commit -m "Some changes"
$ git push
Apply upstream changes...
$ git fetch upstream master
$ git log --all --graph --oneline
$ git merge upstream/master
$ git push
Merge development branch to master
$ git switch master
$ git merge develop
$ git push
$ git log --all --graph --oneline
For next clones:
Clone repository
$ git clone git#github.com:<username>/private-repo.git
$ cd private-repo
Add upstream remote
$ git remote add upstream git#github.com:<username>/public-repo.git
$ git remote --verbose
Switch to development branch and get upstream changes
$ git switch develop
$ git fetch upstream master
$ git log --all --graph --oneline
$ git merge upstream/master
https://gist.github.com/amir-saniyan/a3c76b7e545e3d84f82f27e6c6579245

Related

GitHub: How can I transfer a repo that I own to an organization I own and keep it on my private account?

I have read the help page and I have managed to transfer it to my organization but it is then myorg/repo rather than myuser/repo. I can create a new repo as my org which is myuser/repo though so there must be some way to transfer it like that, but I can't find it.
You have a two options:
Fork the repo (won't be private though)
Clone the repo:
git clone <repo url>
cd <repo directory>
git add . && git commit -m "<commit message>"
git push origin <branch>
Cloning it is the only way to have the same repo but private.

GitHub: how to fork public repo to enterprise, edit enterprise version but still update with public fork

This is a follow up to the question Is it possible to fork a public GitHub repo into an enterprise repository?
I want to fork the public project github.com/foo.git and work on it on my enterprise server, under the name github.enterprise.com/bar.git. However, I want to keep them linked so I can pull any changes on the master. In other words, I am going to create some new codes and edits in my enterprise bar.git, but whenever the authors of foo.git update their master repo, I want to pull those changes. So I followed the following steps.
Create an empty repository on github.enterprise.com/bar.git
Fork github.com/foo.git on my public GitHub account github.com/MyPublic/foo.git
Rename my public repo as to bar.git so it's github.com/MyPublic/bar.git
Create a bare clone of my new fork on my computer
git clone --bare https://github.com/MyPlublic/bar.git
Change directories into the bare clones folder:
cd bar.git/
Push the repository with the --mirror flag to my enterprise GitHub
git push --mirror https://github.enterprise.com/bar.git
git remote set-url --push origin https://github.enterprise.com/bar.git
Now I have the bar.git/ directory on my computer, which is BARE:master and not an editable version of the repo. I have bar.git repos on my personal public GitHub.com account and on my Enterprise server. The next things I need to do are (1) clone the enterprise repo onto my computer and edit it; (2) commit and push those changes to the enterprise repo; and (3) I also want to pull changes from the master foo.git repo when they happen.
I'm assuming I just do a standard clone, commit, and push for (1) and (2), i.e.
git clone GitHub.enterprise.com/bar.git
git commit
git push
Is it actually possible to do #3? I'm thinking that in my computer's bar.git/ directory, I execute
git fetch -p origin
git push --mirror
and then in the bar/ directory, I execute a standard git pull?

Forking private Github Repo that may get deleted

I am taking over a project from a previous contractor and all the code is in a private Github repo. I forked it which now appears as a private repo in my account but I read that if he closes his private repo (which will happen) then my forked repo will get deleted.
So, what's the best way to get this into my own Private repo with all the history behind it? Should I just clone the fork now to my own Private repo?
Just clone your fork using --bare option, and next push it to another remote using --mirror option:
$ git clone --bare https://github.com/exampleuser/old-repository.git
$ cd old-repository.git
$ git push --mirror https://github.com/exampleuser/new-repository.git
For more details look into this GitHub help page.

How to clone project from different branch in visual studio 2015? [duplicate]

I have a local Git repository in ~/local_repo. It has a few branches:
$ git branch
* master
rails
c
c++
To clone the local repository, I do:
$ git clone ~/local_repo new_repo
Initialized empty Git repository in /home/username/new_repo/.git/
The new_repo master branch points to the local_repo master branch, and I can push / pull.
But I am unable to clone another branch. I want to only pull the branch I want (e.g. rails), so that the new repository has a master branch that pushes to and pulls from local_repo's rails branch, by default. How do I accomplish this, or perhaps something similar with local_repo tracking the master local_repo?
Note: the git1.7.10 (April 2012) actually allows you to clone only one branch:
# clone only the remote primary HEAD (default: origin/master)
git clone <url> --single-branch
# as in:
git clone <url> --branch <branch> --single-branch <folder>
Note:
<url> is the URL of the remote repository, and does not reference the branch cloned
<folder> is the local folder where you want to clone the repository
You can see it in t5500-fetch-pack.sh:
test_expect_success 'single branch clone' '
git clone --single-branch "file://$(pwd)/." singlebranch
'
Tobu comments that:
This is implicit when doing a shallow clone.
This makes git clone --depth 1 the easiest way to save bandwidth.
And since Git 1.9.0 (February 2014), shallow clones support data transfer (push/pull), so that option is even more useful now.
See more at "Is git clone --depth 1 (shallow clone) more useful than it makes out?".
"Undoing" a shallow clone is detailed at "Convert shallow clone to full clone" (git 1.8.3+)
# unshallow the current branch
git fetch --unshallow
# for getting back all the branches (see Peter Cordes' comment)
git config remote.origin.fetch refs/heads/*:refs/remotes/origin/*
git fetch --unshallow
As Chris comments:
the magic line for getting missing branches to reverse --single-branch is (git v2.1.4):
git config remote.origin.fetch +refs/heads/*:refs/remotes/origin/*
git fetch --unshallow
With Git 2.26 (Q1 2020), "git clone --recurse-submodules --single-branch" now uses the same single-branch option when cloning the submodules.
See commit 132f600, commit 4731957 (21 Feb 2020) by Emily Shaffer (nasamuffin).
(Merged by Junio C Hamano -- gitster -- in commit b22db26, 05 Mar 2020)
clone: pass --single-branch during --recurse-submodules
Signed-off-by: Emily Shaffer
Acked-by: Jeff King
Previously, performing "git clone --recurse-submodules --single-branch" resulted in submodules cloning all branches even though the superproject cloned only one branch.
Pipe --single-branch through the submodule helper framework to make it to 'clone' later on.
One way is to execute the following.
git clone user#git-server:project_name.git -b branch_name /your/folder
Where branch_name is the branch of your choice and "/your/folder" is the destination folder for that branch. It's true that this will bring other branches giving you the opportunity to merge back and forth.
Update
Now, starting with Git 1.7.10, you can now do this
git clone user#git-server:project_name.git -b branch_name --single-branch /your/folder
Using Git version 1.7.3.1 (on Windows), here's what I do ($BRANCH is the name of the branch I want to checkout and $REMOTE_REPO is the URL of the remote repository I want to clone from):
mkdir $BRANCH
cd $BRANCH
git init
git remote add -t $BRANCH -f origin $REMOTE_REPO
git checkout $BRANCH
The advantage of this approach is that subsequent git pull (or git fetch) calls will also just download the requested branch.
You can try the long-winded way:
mkdir newrepo.git
cd newrepo.git
git init
git remote add origin file:///path/to/original
git fetch origin branchiwant:refs/remotes/origin/branchiwant
git checkout -b branchiwant --track origin/branchiwant
What this does is:
Create and init an empty Git repository.
Adds the original repository as a remote called origin.
Fetches only the branch you require from the remote called origin.
Creates and checks out a new branch that is set up to track the source branch you just cloned.
Hopefully that will be something like what you are after.
git clone <url> --branch <branch> --single-branch
Just put in URL and branch name.
You can do it by using the below command:
git clone -b branch_name --single-branch project_url local_folder_to_clone_in
From git-clone man page:
--single-branch is your friend during clone
remember to use with --branch <branch name> or only remote primary HEAD will be cloned (master by default)
Always remember to do Ctrl + F5 to read fresh source, not the one from cache :-)
(I didn't so didn't know about this option for long time.)
Clone only one branch. This is the easiest way:
git clone -b BRANCH_NAME --single-branch git#bitbucket.org:___/PROJECTNAME.git
There are ample answers here which mention:
Download 1 branch (with the --single-branch part):
# (We'll refer to this as "the 1st command" below.)
# 1. Clone ONLY `branch_name`, then check it out. The `--single-branch` part
# means that ONLY `branch_name` is cloned, fetched, pulled, and
# tracked. _No other remote branches will be cloned to your PC
# whatsoever._
git clone -b branch_name --single-branch \
https://github.com/some_project/some_project.git
...or some version of that, and a few which mention just:
Download all branches (withOUT the --single-branch part):
# (We'll refer to this as "the 2nd command" below.)
# 2. Clone ALL remote branches, then `git checkout` the `branch_name`
# branch.
git clone -b branch_name \
https://github.com/some_project/some_project.git
But, I'd like to expound upon these two things a bit and show a more familiar set of equivalent commands so we can see what is happening with each under-the-hood.
Let's assume that you have a remote repo on GitHub at https://github.com/micronucleus/micronucleus.git, with remote branches master and version_2.5 (this is a real example you can actually run right now).
Breakdown of the 2nd command from above:
The 2nd command (git clone -b version_2.5 https://github.com/micronucleus/micronucleus.git) clones ALL REMOTE BRANCHES to your local PC, but then checks out the version_2.5 branch instead of the master branch. That one command is the equivalent of doing this:
git clone https://github.com/micronucleus/micronucleus.git
cd micronucleus # cd into the repo you just cloned
git checkout version_2.5
# To be pedantic, also delete the local `master` branch since
# technically it won't exist yet since you haven't yet checked
# it out with `git checkout master`, which would create it from
# your locally-stored remote-tracking branch, `origin/master`
git branch -d master
The -b version_2.5 part automatically checked out the version_2.5 branch for us instead of master.
git branch -a shows us that ALL branches, however, were cloned to our local PC. Here you can see our local branch version_2.5, which we are on, plus the locally-stored remote-tracking branches origin/HEAD (which points to origin/master), plus origin/master, and origin/version_2.5:
$ git branch -a
* version_2.5
remotes/origin/HEAD -> origin/master
remotes/origin/master
remotes/origin/version_2.5
We can also look at what our fetch references are. You can either open up the .git/config file to see them directly, or just run git config remote.origin.fetch:
$ git config remote.origin.fetch
+refs/heads/*:refs/remotes/origin/*
You can see above that our git fetch command (which is also triggered by git pull since that is equivalent to git fetch && git merge) is configured to fetch ALL heads for ALL branches in the origin remote. I'm not an expert on this part, but I believe that's what +refs/heads/*:refs/remotes/origin/* means.
Breakdown of the 1st command from above:
The 1st command (git clone -b version_2.5 --single-branch https://github.com/micronucleus/micronucleus.git) clones ONLY the version_2.5 branch to your local PC, and it also checks it out. That one command is the equivalent of doing this (in the end result at least, except that it also downloads much less data in the beginning since it only clones ONE branch NOT all of them):
git clone https://github.com/micronucleus/micronucleus.git
cd micronucleus # cd into the repo you just cloned
git checkout version_2.5
# Delete ALL other branches, including remote-tracking ones, which are not the
# `version_2.5` branch:
# One local branch
git branch -d master
# ALL other locally-stored remote-tracking branches
git branch -dr origin/HEAD
git branch -dr origin/master
# Fix your `.git/config` file so that `git fetch` does the right thing, fetching
# ONLY the `version_2.5` branch head from the `origin/version_2.5` remote branch:
git config remote.origin.fetch \
"+refs/heads/version_2.5:refs/remotes/origin/version_2.5"
The -b version_2.5 part caused the version_2.5 branch to be checked out instead of the master branch by default (as previously explained above), and the --single-branch part caused:
NONE of the other branches to be cloned to our PC, and
git fetch to be configured such that NONE of the other branches will ever be fetched when we call git fetch or git pull!
This command truly cloned and will fetch only the one branch we wanted, and that's it!
git branch -a shows us that ONLY the version_2.5 branch was cloned and checked out. Here we see by the * which branch is checked-out, and we see also that we have a locally-stored remote-tracking branch for origin/version_2.5:
$ git branch -a
* version_2.5
remotes/origin/version_2.5
We can also look at what our fetch references are. You can either open up the .git/config file to see them directly, or just run git config remote.origin.fetch:
$ git config remote.origin.fetch
+refs/heads/version_2.5:refs/remotes/origin/version_2.5
You can see above that our git fetch command will only fetch the version_2.5 branch head from the origin/version_2.5 remote branch. That's it! Beware that no other remote branches will ever be fetched.
Summary:
So, now you see that using -b branch_name basically just ensures the branch_name branch is checked-out after the clone, but still clones ALL remote branches, whereas adding also --single-branch ensures that ONLY branch_name is cloned, fetched, pulled, and tracked. No other remote branches will be cloned to your PC whatsoever.
Personally, I prefer the -b branch_name option alone, because I want all branches cloned to my local PC. The one exception might be on a huge, shared mono-repo which has dozens, or even hundreds or thousands of remote branches. In that case, just use -b branch_name --single-branch to clone just the one main branch you care about and be done. Better to download 50 GiB of data for the master branch in a huge mono-repo, for instance, than to download 200 GiB of data so you can have 2000 of your peers' branches they are working on too!
References:
Clone only one branch
How do you stop tracking a remote branch in Git?
git clone --branch <branchname> <remote-repo-url>
or
git clone -b <branchname> <remote-repo-url>
For cloning a specific branch you can do :
git clone --branch yourBranchName git#yourRepository.git
For cloning a branch of Git you don't have the public key to, use this:
git clone -b <branch> <Git repository URL or clone URL you get from Git repository>
🏎️ Some Performance Measurements 🏎️
I compared two of the suggested approaches, and found that one is way faster (and smaller) than the other (which is advantageous if your only goal is to clone, and you don't care about much else).
I found that the most important performance indicator is --depth, meaning that VonC's answer is the fastest.
Try it yourself:
time bash -cl "git clone --single-branch --depth=1 --branch=$MYBRANCH $MYGITURL"
I tested this with a big project with a long history and many branches, and this approach takes about 6s.
Note that, contrary to what is claimed by several comments in this thread, (at least in a recent git version), this will only checkout the target branch. git branch -a only lists that single branch.
The Runner Up
By comparison, frerich-rabe's approach consistently took 26s:
time bash -cl "git init && git remote add -t $MYBRANCH -f origin $MYGITURL && git checkout $MYBRANCH"
When comparing the two, it is also important to note that, in my case, the target branch is a much slimmed down version of its parent branch. The first approach's download progress bar reflects that reduction in size (< 10MB), while the second does not (> 90MB). (I'm sure, there are more mature methods to measure total download size, but I have not looked into that yet.)
A little late but I wanted to add the solution I used to solve this problem. I found the solution here.
Anyway, the question seems to be asking 'how to start a new project from a branch of another repo?'
To this, the solution I used would be to first create a new repo in github or where ever. This will serve as the repo to your new project.
On your local machine, navigate to the project that has the branch you want to use as the template for your new project.
Run the command:
git push https://github.com/accountname/new-repo.git +old_branch:master
What this will do is push the old_branch to new-repo and make it the master branch of the new repo.
You then just have to clone the new repo down to your new project's local directory and you have a new project started at the old branch.
Let us take the example of flask repo. It has 3 branches in addition to master. Let us checkout the 1.1.x remote branch
clone the git repo
git clone https://github.com/pallets/flask
cd into the repo.
cd flask
fetch remote branch 1.1.x
git fetch origin 1.1.x
checkout the branch
git checkout 1.1.x
You will switch to the branch 1.1.x and it will track the remote 1.1.x branch.
Open the cmd.
cd folder_name # enter the path where to clone the branch
Just one command:
git clone url_of_projecturltoclone -b branch_name
There are primarily 2 solutions for this:
You need to specify the branch name with -b command switch. Here is the syntax of the command to clone the specific git branch.
git clone -b <BRANCH_NAME> <GIT_REMOTE_URL>
Example:
git clone -b tahir https://github.com/Repository/Project.git
The following command will clone the branch tahir from the git repository.The above command clones only the specific branch but fetches the details of other branches. You can view all branches details with command.
git branch -a
You can use --single-branch flag to prevent fetching details of other branches like below:
git clone -b <BRANCH_NAME> --single-branch <GIT_REMOTE_URL>
Example:
git clone -b tahir --single-branch \
https://github.com/Repository/Project.git
Now if you do a git branch -a, it will only show your current single branch that you have cloned and not all the branches. So it depends on you how you want it.
If you want a shallow clone, you can do this with:
git clone -b mybranch --depth=1 https://example.com/myproject.git localname
--depth=1 implies --single-branch.
you can use this command to git single branch and rename the folder if you want to keep branched stand alone
git clone -b [branch-name] --single-branch [url] [folder_name]
example
git clone -b mybranch --single-branch git://github/repository.git project_mybranch
This should work
git clone --single-branch <branchname> <remote-repo-url>
git clone --branch <branchname> <remote-repo-url>
I did it this way
git clone -b <branch_name> url
example :
git clone -b master https://gitlab.com/jhondoe/applicationproject.git
or
git clone -b master git#gitlab.com:jhondoe/applicationproject.git
git clone --single-branch -b [branch name] [repository URL]
Similar to what #nosaiba-darwish said here: here
This is what we usually do in our company:
git clone -b <name_of_branch> --single-branch <git_url> folder_to_clone_locally
For the newbies like me,
just run the code below
git clone https://gitlab.com/repo/repo.git --branch <name of branch> --single-branch
Usign Github CLI
If you are cloning a repo using the Github CLI, clone options must be declared differently.
--depth=1
gh repo clone username/repo -- --depth=1
--single-branch
gh repo clone username/repo -- --single-branch
--branch
gh repo clone username/repo -- --branch main --single-branch localDir
git clone --branch {branch-name} {repo-URI}
Example:
git clone --branch dev https://github.com/ann/cleaningmachine.git
dev: This is the {branch-name}
https://github.com/ann/cleaningmachine.git: This is the {repo-URI}
Can be done in 2 steps
Clone the repository
git clone <http url>
Checkout the branch you want
git checkout $BranchName

Fork a github repo and push to my private repo

I am taking a class which has a classwide github repo to publish labs, docs, etc. I want to fork this, do my own work on the labs, and push to my private git repo. However, I still want to be able to pull changes from the class github. Is there a way to do this?
Thanks
set up two remote branches, one for your private and one to the class
git remote add classwide sshblah
git remote add private sshblah
then you can
git fetch classwide
to grab your class stuff and
git merge localbranch
to work on it, then you can
git push localbranch private
to put it into your private repo
Yes, for sure, the key is in your repo remotes, so your fork have a remote called "origin" and for the original repo create a remote called upstream.
create the upstream remote with following command
git remote add upstream https://github.com/user/original.git
Then validate your remotes
git remote -v
origin https://github.com/your-user/fork.git (fetch)
origin https://github.com/your-user/fork.git (push)
upstream https://github.com/user/original.git (fetch)
upstream https://github.com/user/original.git (push)
So now you can push and pull from the original repo
git pull upstream branch
git push upstream branch
In the other way you can create a pull request directly in Github