Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

I tried to clone a repository from git using GitPython in python function. I used GitPython library for cloning from git in my python function and my code snippet as follows:

from git import Repo

Repo.clone_from(' http://user: [email protected] /user/project.git ', /home/antro/Project/')

It clones from master branch. How do I clone from other branch using GitPython or any other library is available to clone from individual branches? Please let me know.

I am aware of clone by mentioning branch in commandline using

git clone -b branch http://github.com/user/project.git

There is no such thing as "cloning from a branch". When you clone, you clone the whole repo. What clone -b does is, after cloning the entire repo, it checks out the specific branch instead of the default branch (which is usually master ). So instead of looking for something exotic, why not just do a branch checkout after the clone? Mark Adelsberger Apr 20, 2017 at 13:29 @MichałPolitowski - Oh, yes. That. I forget about that because it has only ever caused me trouble. Any more I only use the negation of that flag (for making shallow repos that aren't hobbled). Well, I would still take the position that OP probably means just to check out the branch and is conflating terms, since the CLI command specified in the question does clone the whole repo. Mark Adelsberger Apr 20, 2017 at 13:41 @MarkAdelsberger How to checkout into another branch in python function. and clone -b clones particular branch, it exist Antony Apr 20, 2017 at 13:42 @Antro - If I knew the python command I'd have posted an answer instead of a comment. And no, clone -b does not clone a particular branch. It checks out a particular branch. Mark Adelsberger Apr 20, 2017 at 13:43
repo = Repo.clone_from(
    'http://user:[email protected]/user/project.git',
    '/home/antro/Project/',
    branch='master'

see here for more info

From toanant's answer.

This works for me with the --single-branch option

repo = Repo.clone_from(
    'http://user:[email protected]/user/project.git --single-branch',
    '/home/antro/Project/',
    branch='master'

GitPython uses a keyword args transformation under the hood:

# cmd.py
def transform_kwarg(self, name: str, value: Any, split_single_char_options: bool) -> List[str]:
    if len(name) == 1:
        if value is True:
            return ["-%s" % name]
        elif value not in (False, None):
            if split_single_char_options:
                return ["-%s" % name, "%s" % value]
            else:
                return ["-%s%s" % (name, value)]
    else:
        if value is True:
            return ["--%s" % dashify(name)]
        elif value is not False and value is not None:
            return ["--%s=%s" % (dashify(name), value)]
    return []

A resulting list of command parts is fed into subprocess.Popen, so you do not want to add --single-branch to the repo URL. If you do, a strange list will be passed to Popen. For example:

['-v', '--branch=my-branch', 'https://github.com/me/my-project.git --single-branch', '/tmp/clone/here']

However, armed with this new information, you can pass any git CLI flags you like just by using the kwargs. You may then ask yourself, "How do I pass in a dash to a keyword like single-branch?" That's a no-go in Python. You will see a dashify function in the above code which transforms any flag from, say, single_branch=True to single-branch, and then to --single-branch.

Full Example:

Here is a useful example for cloning a single, shallow branch using a personal access token from GitHub:

repo_url = "https://github.com/me/private-project.git"
branch = "wip-branch"
# Notice the trailing : below
credentials = base64.b64encode(f"{GHE_TOKEN}:".encode("latin-1")).decode("latin-1")
Repo.clone_from(
    url=repo_url,
    c=f"http.{repo_url}/.extraheader=AUTHORIZATION: basic {credentials}",
    single_branch=True,
    depth=1,
    to_path=f"/clone/to/here",
    branch=branch,

The command list sent to Popen then looks like this:

['git', 'clone', '-v', '-c', 'http.https://github.com/me/private-project.git/.extraheader=AUTHORIZATION: basic XTE...UwNTo=', '--single-branch', '--depth=1', '--bare', '--branch=wip-branch', 'https://github.com/me/private-project.git', '/clone/to/here']

(PSA: Please do not actually send your personal tokens as part of the URL before the @.)

thank you for the example and the explanation. I'd like to understand why you're doing credentials = base64.b64encode(f"{GHE_TOKEN}:".encode("latin-1")).decode("latin-1"). – cybervedaa Feb 21, 2022 at 19:46 Ah. IIRC b64encode results in bytes. The RFC spec wants the authorization header in latin-1 (ascii). So I encoded the token in latin-1 first to be sure it could be decoded correctly, ran base64 to get bytes, then decoded it back to ascii to be certain the HTTP header will accept it. The first latin-1 could be skipped, perhaps, but it is userland input, so sneaky, invisible UTF-8 spaces could make their way into the token. Some people watermark their code/strings or add invisible chars to try for buffer overflows, so I got in the habit of defensive coding as well. Good question. – Drakes Feb 21, 2022 at 21:47

For --single-branch option, you can just pass a single_branch argument to the Repo.clone_from() method:

Repo.clone_from(repo, path, single_branch=True, b='branch')
        

Thanks for contributing an answer to Stack Overflow!

  • Please be sure to answer the question. Provide details and share your research!

But avoid

  • Asking for help, clarification, or responding to other answers.
  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.