3

I can't add origin/master as tracking branch to the local master branch

git checkout --track origin/master
fatal: 'origin/master' is not a commit and a branch 'master' cannot be created from it

My fork has some commits in it already. Remote(fork) also has 1 commit with README in it. What can be the problem?

Edit: after running git fetch origin, the error message changes:

git checkout --track origin/master
fatal: A branch named 'master' already exists.
torek
  • 448,244
  • 59
  • 642
  • 775
ccvhd
  • 202
  • 3
  • 10
  • @eftshift0 no, git branch -r is empty – ccvhd Nov 20 '19 at 20:44
  • 1
    That can't be good if this is a fork... unless you forked from an empty repo. – eftshift0 Nov 20 '19 at 20:45
  • @eftshift0 fetched origin and now it's listed, but still can't track. git checkout --track origin/master fatal: A branch named 'master' already exists. – ccvhd Nov 20 '19 at 20:46
  • Is master already tracking origin/master? `git branch -vv` If not, `git checkout master` then `git branch -u origin master` – EncryptedWatermelon Nov 20 '19 at 21:02
  • @EncryptedWatermelon git branch -u origin master error: the requested upstream branch 'origin' does not exist hint: hint: If you are planning on basing your work on an upstream hint: branch that already exists at the remote, you may need to hint: run "git fetch" to retrieve it. hint: hint: If you are planning to push out a new local branch that hint: will track its remote counterpart, you may want to use hint: "git push -u" to set the upstream config as you push. – ccvhd Nov 20 '19 at 21:58
  • @EncryptedWatermelon but i've already fetched remote, and even tried again to fetch and branch -u – ccvhd Nov 20 '19 at 21:59

3 Answers3

3

It's not clear to me how you created your local repository in the first place, but I suspect you did this:

mkdir new-repo
cd new-repo
git init

and then created some files and git added them and committed the result. This would leave you with a new repository with just one commit in it, and no origin remote, so you would then have had to run:

git remote add origin ssh://git@github.com/your/repo.git

or similar.

It's not clear to me how you created your/repo.git (or whatever its path may be) on GitHub, but I suspect you used the "create a new repository with a README file in it" button.

If all of these "suspects" are correct, this explains everything. Your initial error:

fatal: 'origin/master' is not a commit and ...

occurred because you had not yet connected your Git to GitHub's Git that holds the repository you created at GitHub.

You then ran git fetch origin, which had your Git connect to their Git and obtain their (single) commit containing a README file. Your Git copied their commit into your repository. Your Git then created your own origin/master remote-tracking name, to remember the hash ID of their (single) commit.

You now have two initial (created-from-nothing) commits, which Git calls root commits. If we draw a diagram of your repository, it might look like this:

A   <-- master

B   <-- origin/master

Your first commit, represented here as A—whatever its actual hash ID might be—holds the files you committed. Your branch name master identifies this one commit.

Their first commit, represented here as B, holds the files they committed. Your remote-tracking name origin/master identifies this one commit.

You now ask your Git to create a new branch name master pointing to commit B, using your origin/master, via the failing command:

git checkout --track origin/master
fatal: A branch named 'master' already exists.

The reason for the error message is clear: you already have a branch name master, pointing to existing commit A; it's not possible to create a new but identical branch name master pointing to existing commit B.

What to do about this

You have a number of options for proceeding from here. They mostly involve creating a new commit C.

You can join your history (your one lone commit) to their history (their one lone commit) by using git merge. To do so, you will need the --allow-unrelated-histories option, unless your version of Git is old enough not to have the option. A Git that old just assumes that --allow-unrelated-histories should always be implied.

If their lone commit B is autogenerated, merging histories like this is a bit silly. It would make more sense to just throw out their commit entirely. Take anything you find useful from their commit B and make your own new regular commit C:

A <-C   <-- master

B   <-- origin/master

Your new commit C will point only to your existing A. You can now force them to throw away their commit B, sending them your new C.

Or, you can go ahead and merge the two commits:

A
 \
  C   <-- master
 /
B   <-- origin/master

You can now send them commit C and ask them to make their master remember C, which remembers both A and B.

To send them new commit C (which will bring with it A, and point back to A, and maybe also to B depending on how you made C), use git push origin master. This sends C (and A) and ends with a polite request that they please, if they would, make their name master point to C. If you deliberately threw out B, by not making a merge, you'll need to upgrade the polite request to a command: git push --force origin master.

When this is all done, their master will also point to (their copy of the now-shared) commit C. Your Git will update your own origin/master to remember that their master remembers C, and you'll both agree that C is the last commit of your and their branches, both of which are named master.

Meanwhile, your own master won't have origin/master set as its upstream. There's no reason it must be, but if you'd like it to be—see Why do I need to do `--set-upstream` all the time?—you can use git branch --set-upstream-to, or you can combine your git push with the -u option:

git push -u origin master

or:

git push --force -u origin master

(with the --force option only required when you're telling them: *forget about your commit B, it's useless, use my C instead—which is not required if your C points back to B).

Instead of either merge or override, you have yet more options, which also create a new commit C. You can:

  • rebase your A on their B, using git rebase -i --root, or
  • copy your A to a new commit C that sits atop their B, on a new branch not named master.

The rebase works by doing the copy, then abandoning your original A in favor of this new C:

A   [abandoned / lost - will eventually be garbage collected]

B   <-- origin/master
 \
  C   <-- master

Or:

A   <-- master

B   <-- origin/master
 \
  C   <-- newbranch

You can then rename your master, e.g., to old-master and rename newbranch to master:

A   <-- old-master

B   <-- origin/master
 \
  C   <-- master

In the end, you can now git push -u origin master to send them commit C (this time without sending A at all) and ask them to set their master to point to new commit C.

How to make sense of all of this

Go back and re-examine all of the earlier diagrams and think about things like this:

  • What matters to Git are the commits, which never change (but can be abandoned and eventually tossed entirely).
  • Names, like master and origin/master, merely serve to find the last commit in some sequence of commits.
  • The hash ID of any commit—you'll see these big ugly hash IDs in git log output—is how Git finds a commit. By storing the last hash ID in each name, Git can find all the last ones. Each commit itself stores the big ugly hash ID of its immediate predecessor: commit C points back to commit A, or commit B, or both, depending on how we make it.

It's the commits that actually matter. Git gives you the names, because names mean something to humans (who can't remember big ugly hash IDs), and then uses the names to find the commits. Those commits that Git can find by name, store hash IDs of earlier commits. Those earlier commits store hash IDs of even-earlier commits, and so on. The git log command just starts at the current end and works backwards, showing you commits as it goes.

torek
  • 448,244
  • 59
  • 642
  • 775
1
  • Get latest version
    git fetch -apt
  • Check if your remote is correct with
    git remote -v
    If the remote is not correct please do git remote add origin <your repo>
  • Save your current master branch with a tag:
    git tag -l old-master
  • Remove your local master (you already saved it with the tag)
    git branch -D master
  • Get the latest remote master
    git switch -c <branch> --track <remote>/<branch>
Giulio Caccin
  • 2,962
  • 6
  • 36
  • 57
0

We were having this exact error in a Windows machine running gitbash on a folder synced with google drive.

It was caused by having the feature "Enable experimental built-in file system monitor" enabled.

After uninstalling and reinstalling gitbash with this feature disabled it was fixed.

enter image description here

Luciano
  • 992
  • 1
  • 9
  • 17