Aditya Rewari
Aditya Rewari

Reputation: 2687

Did a git reset --hard, but still conflicts at git pull

I did a git reset --hard

I do not understand, that upon git reset --hard there should be no local changes(Verified through git status also)

Then why the conflict arising ?

As per my understanding, conflict occurs, when there are changes at the same line. But, this scenario should not occur, as I have done a git reset --hard

enter image description here

Upvotes: 3

Views: 5477

Answers (3)

torek
torek

Reputation: 488463

There's a flaw in your reasoning here:

[after] git reset --hard there should be no local changes (Verified through git status also)

The fact that git status says:

nothing to commit, working tree clean

does not mean that there are no "local changes". It means there are no uncommitted changes.

About git pull: I recommend not using it

Both kinds of git pull—with or without --rebase—means run git fetch, then run a second Git command. The version with --rebase means use git rebase as the second command, instead of the default command. The default command depends on how you've configured your git pull; if you have not configured it at all, the default default is git merge.

The git pull command is meant to be convenient. After your git fetch, you will usually want to incorporate fetched commits, and to do so, you will generally use either git merge or git rebase. The git pull command combines both of the two commits—fetch-then-merge, or fetch-then-rebase—into one more-convenient command. The problems with combining them include:

  • This means you can't insert any commands between the two commands. You can't look to see what git fetch fetched, before you try to incorporate these. That's a bit like opening your door when the doorbell rings, then jumping into a delivered box that you expect to contain pillows. What if they delivered a box of snakes instead? Maybe it would be wise to look before you leap.1

  • If something goes wrong (as it did here), you may not know what to do to recover.

  • The pull command's syntax is weird: it's different from all other Git commands, in ways that are tricky to explain. It's at least sort of similar to git push, but thinking along these lines misleads, because pull and push do not go together that well: the opposite of push is really fetch, not pull.


1There are valid objections to this philosophy. You can undo things, once you know how. If you're well versed in all things Git, feel free to pick whichever method works best for you. I use a mix of pull or fetch-then-command, myself.


So why are conflicts arising?

Your image shows that you're already in the partially-merged, merge-or-rebase-still-ongoing-but-hasn't-completed phase of a git pull that ran one of those second commands. When you are in this state, many Git commands cannot proceed. That includes git pull.

To get out of this state, you must either finish the in-progress command—whether that's git merge or git rebase—or stop it entirely. To stop it entirely, you can use:

  • git merge --abort, if it is a merge that is in progress; or
  • git rebase --abort, if it is a rebase that is in progress; or
  • git reset --hard, regardless of which of these two is in progress.

All three commands put you back to where you were before you started, with some caveats. (I won't go into details as I am short on time.)

We can't say for certain exactly why you are getting conflicts—not without access to your repository, anyway. But a crucial thing to know about Git is that Git is all about commits. Commits are the unit of storage at which you work in Git. Commits are mostly permanent—they live as long as you can find them—and are completely, totally, 100% read-only. You can never change anything about any commit.

Each commit has a unique hash ID. This hash ID is the same in every Git everywhere. That makes it easy for your Git and any other Git to exchange commits. They just check: do they both have that hash ID? If so, they both have that commit. If not, the one that has the commit can give it to the other Git.

Each commit stores a complete snapshot of all of your files. The files inside a commit are frozen: no part of any commit can ever be changed, including the stored files. The files themselves are stored in a special, read-only, compressed and Git-only format, in which Git does de-duplication too, so the fact that every commit has every file doesn't cost anything: if a thousand commits have a thousand copies of some file, but all those copies are the same, there's really only one copy after all.

Any branch name, or any other name such as a tag name or a remote-tracking name, just stores the raw hash ID of one commit. It's the commits themselves that form into structures. See What exactly do we mean by "branch"? The branch names identify the last commit in some series of commits.

When you run git fetch, you have your Git call up some other Git and get any new commits from them. Your Git and their Git look over the various hash IDs and figure out which commits they have, and you don't. Your Get gets their commits and now you share commits—but you can have commits they don't.

When you run git merge, you pick out some commit of theirs—usually by a remote-tracking name like origin/master or origin/dev, and often you have your own master or dev`, maybe for a different last commit—and tell your Git: combine what I have now, with what's in that commit. If you have commits that they don't, and they have commits that you didn't before, this combining can result in merge conflicts.

When you run git rebase, you pick out some commit of theirs and tell your Git: copy commits I have now, that they don't, so that they build on their last commit. This copying process can result in merge conflicts.

If you have commits that they didn't, and you did not expect to have commits that they didn't, you should figure out why that's the case. But that's almost certainly the case here.

Upvotes: 1

HardcoreHenry
HardcoreHenry

Reputation: 6387

git reset --hard syncs what you have in your workspace to what's in your local repository (to whatever commit id you happen to be pointing to). git pull pulls commits from the remote into your local repository, and then tries to merge your workspace to the latest commit -- where it detects a conflict.

What's likely happening is that you submitted a commit to your local repository, and it conflicts with something being pulled down. If you did not commit anything, it's also possible that someone did a rebase on the remote repository, or your remote branch has changed, and what you have conflicts with what's being pulled down. Check the logs of what you have in your local branch vs what's in the remote and it should shed some light on this.

Upvotes: 2

eftshift0
eftshift0

Reputation: 30232

It could still happen if you have ignored (by you) files that are coming from the PR. Is that the case?

Upvotes: 0

Related Questions