5

I have a local repo with some commits. As I want to make it publicly available to others, I need to push it to a newly created remote repo at Github. The newly created remote repo is initialized with a license file (because the local repo has no license file).

Pushing with git push -u origin main (my local branch also uses main instead of master as the primary branch) produces an error because of the license file added in the remote repo.

C:\test>git push -u origin main
To https://github.com/pstricks-fans/test.git
 ! [rejected]        main -> main (fetch first)
error: failed to push some refs to 'https://github.com/pstricks-fans/test.git'
hint: Updates were rejected because the remote contains work that you do
hint: not have locally. This is usually caused by another repository pushing
hint: to the same ref. You may want to first integrate the remote changes
hint: (e.g., 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details. 

And I follow the hint by pulling as follows.

C:\test>git pull origin main
From https://github.com/pstricks-fans/test
 * branch            main       -> FETCH_HEAD
fatal: refusing to merge unrelated histories

Merging is not possible.

Someone told me I have to rebase with the following.

C:\test>git pull origin main --rebase
From https://github.com/pstricks-fans/test
 * branch            main       -> FETCH_HEAD
Successfully rebased and updated refs/heads/main.

Question

Is there any other solution without rebasing (for learning purposes)? Rebasing is not recommended for public repo (as the git documentation says).

4
  • 2
    "Rebasing is not recommended for public repo" I think the question is based on a misunderstanding. You should not modify (e.g., by rebasing) existing public history. But there is nothing wrong with rebasing your local commits on a public branch.
    – CL.
    Commented Apr 10, 2022 at 15:03
  • @CL.: Good point. Thanks! Commented Apr 10, 2022 at 15:19
  • 1
    You can use git pull origin main --allow-unrelated-histories to merge, if that's what you really want. See stackoverflow.com/a/38680153/182705 for example.
    – Neil
    Commented Apr 10, 2022 at 17:25
  • 1
    @Neil: Thanks. It works! If you don't mind you may post it as your answer and I will accept it. :-) Commented Apr 10, 2022 at 18:15

3 Answers 3

5

You have three options for your final history.

  1. Your local commits are unchanged, plus you have a further local commit which contains the licence file. One way to do this is to use git cherry-pick origin/master to rebase the public commit onto your local branch and then git push --force-with-lease to overwrite the public branch with your branch. Although overwriting public branches is normally inadvisable, this isn't a problem if nobody else has actually cloned it yet.

  2. As you know you can rebase your local commits so their history now follows that of the licence file commit.

  3. You merge the local and remote branches, but because they don't have a common ancestor, Git is worried that you might be making a mistake, so to reassure it you need to use git pull origin main --allow-unrelated-histories, as discussed in this Stack Overflow question.

3

If you want to make the license file show up in all of your existing commits, then rebasing (or some other form of history rewriting) is the only option. Files cannot be added to existing commits without changing the commit IDs.

(Merging the local and GitHub-initialized histories, although fully possible, won't actually achieve this – the GitHub-provided file will only appear in the 'merged' commit and onwards, but the merge won't change the repository's past contents.)

If you only want the license file to show up on new commits (which is probably fine), then just normally add+commit it to your local repository, then git push --force to GitHub, throwing away whatever it had initialized.

GitHub's "Initialize with..." feature is only meant for brand new repositories – it's useless when publishing an existing repo.

1
  • This is not SVN, you don't need to pull in order to make new commits. Copy & paste the file from GitHub (or from some other source) to your local machine, commit it, and ignore what's on GitHub. Commented Apr 10, 2022 at 7:17
0

Why it happens

git pull does a merge by default. But your two main branches (the remote and your local repository) has unrelated histories (no common ancestor), and merge refuses to do such a merge by default.

Why rebasing is 100% OK

The recommendations against git-rebase(1) are for published history, i.e. things that other people can pull/fetch. But your own changes are still local, so it’s totally fine to do

git pull --rebase origin main
git push origin main

Since the remote history is not clobbered.

Why git-merge(1) won’t combine such histories by default

Because it is likely to be a mistake.

Apparently, when contributing to an existing repository (not making a new one like you did), it is (or at least was) possible to accidentally make an “orphan branch” which is not connected to the branch that you intend to merge into.

This happened in the Linux Kernel [1] when someone made a new root commit with a readme file (the commit snapshot only contained that file). This wasn’t intended by the author. [2]

But such unrelated merges are sometimes intended, like when you want to merge a whole other project into your own. But that is such a rare occurrence that one is expected to provide the long switch --allow-unrelated-histories in such cases.

Notes

  1. Via

  2. git-merge(1) learned --allow-unrelated-histories in e379fdf34f (merge: refuse to create too cool a merge by default, 2016-03-18), when it was taught to disallow such merges without that switch:

    merge: refuse to create too cool a merge by default

    While it makes sense to allow merging unrelated histories of two projects that started independently into one, in the way "gitk" was merged to "git" itself aka "the coolest merge ever", such a merge is still an unusual event. Worse, if somebody creates an independent history by starting from a tarball of an established project and sends a pull request to the original project, "git merge" however happily creates such a merge without any sign of something unusual is happening.

    Teach "git merge" to refuse to create such a merge by default, unless the user passes a new "--allow-unrelated-histories" option to tell it that the user is aware that two unrelated projects are merged.

    Because such a "two project merge" is a rare event, a configuration option to always allow such a merge is not added.

    […]

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .