I have shallow cloned a repo with depth 1 and create a local dev branch for development. After raising the PR, I have received merge conflicts, So I have pulled the latest master and tried to merge it with the dev branch.
Approach 1:
fatal: refusing to merge unrelated histories
git switch -c master origin/master
fatal: refusing to merge unrelated histories
Approach 2:
bad object
.I have tried –allow-unrelated-histories
, there were so many merge conflicts that had to be hand fixed.
How to resolve this issue and merge master to my dev branch?
Never1 use --allow-unrelated-histories
. Instead, deepen (or "unshallow") your clone. Edit: as per comments, you also need to convert your clone to a full clone (it's currently a single-branch clone, which I should have anticipated since using --depth
during cloning defaults to creating a single-branch clone as well).
Merging, in Git, depends on three commits, not two:
HEAD
), which will represent work done since some common starting point;When you run git merge
, the argument you supply—generally a branch name like feature
or master
—locates the middle of these three: the "other" or --theirs
commit. The current or --ours
commit is implied by what you have checked out. The third commit, the common starting point, Git finds on its own. But Git needs the history to find this commit.
History, in a Git repository, is nothing more or less than the commits in the repository. A normal, non-shallow clone has all the commits,2 so it has all the history. The point of a shallow clone is to deliberately omit some history in the name of expediency. For some purposes, this is fine (and hence actually expedient). For merging it's not fine; don't do it.
If you have an existing shallow clone, e.g., because your CI system made one, consider running:
git remote set-branches origin "*"
git fetch --unshallow
The first command converts the clone to a standard full clone (undoing the single-branch-ness). Note that you may be able to type in the *
without quotes, but using the quotes like this should always work.
The second command redirects the usual git fetch
operation such that it removes the shallowness. If this proves to use too much in the way of system resources, you can alternatively use git fetch --depth
or git fetch --deepen
to incrementally add more commits to the shallow repository until you have enough history—enough commits—for git merge
to locate the common starting point. The problem with this approach is that there's no guarantee how deep that depth might be, which means there's no correct way to choose the right depth. This in turn implies a loop, where you deepen the depth repeatedly until it's "enough", and that uses more and more system resources each time, which is presumably what you were trying to avoid in the first place through shallow cloning.
Most CI systems that do make shallow clones offer you a way to force a full clone in the first place (which is overall more efficient than making a shallow clone and then un-shallowing it). So if the shallow clone is the problem, as in this case, just don't do it in the first place.
1Rule for advanced Git users: Never use --allow-unrelated-histories
until you've proven somehow that it's OK.
2Remember, the core of a git clone
operation is copy all the commits, but none of the branch names. Git doesn't need branch names to function, but it does need commits. We—humans—don't like using Git without branch names, so we always have Git create some, although CI systems sometimes don't bother with them; we use branch names and/or remote-tracking names (which remember some other repository's branch names) to find the interesting commits. Git can use these as well, but can use the raw hash IDs directly, which is how those CI systems work.