3

I've been working on some Python scripts which make use of the gitpython library to automate the creation of local branches based on issues in our redmine instance. To get started I'm trying to create some local repo's to simulate the system as I expect it to work but I'm falling at the first hurdle.

This is the setup for my test case which should create a 'remote' repo, then clone it to make a local one and finally, create a local feature branch:

def setUp(self):
    # Create a remote git repo to simulate the one gitlab maintains
    baseDir = os.path.join('C:\\', 'test-repos')
    if os.path.exists(baseDir):
        shutil.rmtree(baseDir)

    gitlabRepoLocation = os.path.join(baseDir, 'gitlab')
    gitlabRepo = git.Repo.init(gitlabRepoLocation)

    # Clone to a local repo
    localRepoLocation = os.path.join(baseDir, 'local')
    localRepo = git.Repo.clone_from("file://"+gitlabRepoLocation, localRepoLocation)
    localRepo.create_head('some-feature') # <-- This fails

But when I run it I get:

Traceback (most recent call last):
  File "C:\Projects\PyTools\Gitted\test_Helpers.py", line 70, in setUp
    gitlabRepo.create_head('some-feature')
  File "C:\Python34\lib\site-packages\git\repo\base.py", line 330, in create_head
    return Head.create(self, path, commit, force, logmsg)
  File "C:\Python34\lib\site-packages\git\refs\symbolic.py", line 527, in create
    return cls._create(repo, path, cls._resolve_ref_on_create, reference, force, logmsg)
  File "C:\Python34\lib\site-packages\git\refs\symbolic.py", line 479, in _create
    target = repo.rev_parse(str(reference))
  File "C:\Python34\lib\site-packages\git\repo\fun.py", line 311, in rev_parse
    obj = name_to_object(repo, rev)
  File "C:\Python34\lib\site-packages\git\repo\fun.py", line 124, in name_to_object
    raise BadName(name)
gitdb.exc.BadName: Ref 'HEAD' did not resolve to an object
1
  • 2
    I am just guessing, but it looks like this is a bug in gitpython that assumes that you are never on a branch-yet-to-be-born (in this case HEAD contains a branch name but the branch name does not yet exist and hence HEAD cannot be parsed to a revision, only to a branch-name). There are only two "normal" ways to get a repo into this state: at initial creation, when there are no commits, or using git checkout --orphan <newbranch>. You are encountering the first one.
    – torek
    Commented Apr 11, 2016 at 17:49

3 Answers 3

3

Turns out @torek was correct. Adding and comitting an empty file solved the issue:

    filename = 'readme.txt'
    open(filename, 'wb').close()
    gitlabRepo.index.add([filename])
    gitlabRepo.index.commit("Adding "+filename+ "to repo")
1
  • essentially this is the correct answer, but rather than just committing some random file and committing, you can use that step to commit whatever actual files you are looking to commit. And then creating your first branch(HEAD) from that initial commit. Commented Jul 17, 2017 at 16:36
1

It looks like this is by design, as when you clone an empty repo there are no commits and therefore, no HEAD references, so in order to create a ref to a commit. You need to commit something first. When using git command line you will run into a similar issue.

mkdir empty_repo
cd empty_repo
git --init
git checkout master

The above lines of code will present the error error: pathspec 'master' did not match any file(s) known to git. The reason for this is because there are no commit references to use to create a new HEAD.

But adding and committing a set of files you will then generate the first md5 reference and the first HEAD object.

So this issue can be resolved by changing the order in which you are processing the repo.

  1. Create or clone the empty repo to a local location.
  2. Assert that the cloned repo is indeed new and empty. (if not you can generate as many new HEAD references as needed)
  3. Since it is empty you can add and commit any files you wish.
  4. Create a new HEAD from this first commit.
0

I would agree with torek that this seems to be a bug in gitpython. Jon's soloution would work but it leaves unwanted rubbish in the git repo.

I personally ended up working around the issue by using the git command line tool to create the branch.

command = ['git','branch','-f','workingbranch',parenttagname]                 
print(command, flush=True)
if (subprocess.call(command) != 0): exit(1)
branch = repo.heads.workingbranch

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.