mhkeller
mhkeller

Reputation: 712

Git pull requires a merge but no local changes

I have a webhook on a GitHub repo that triggers a git pull on another server so the repository on the server is always in sync with what's been pushed to GitHub.

Sometimes the pull requires a merge commit but the server version is never committed to or altered. When I look at the diffs, the merge commit shows changes from the last few commits, which makes it seem like the server version is up-to-date and what it's trying to pull down is behind it.

It runs this code to pull down all branches (which can be improved). But in this case, the only branch is master.

git fetch origin for remote in $(git branch -r) ; do git checkout $(echo $remote | cut -d \'/\' -f2) && git pull origin $(echo $remote | cut -d \'/\' -f2); done

When I run git status on the server's version, it says that the local branch is XX ahead of the remote. Where are these changes coming from?

Upvotes: 1

Views: 515

Answers (1)

Chris
Chris

Reputation: 136967

It sounds like you may be modifying commits that have already been pushed to GitHub. There are many ways that this can happen, but two common ones are amending commits and rebasing. Both of these are fine to do with local commits, but doing it with shared commits often causes trouble.

Consider a simple repository on GitHub:

A---B---C  [master]

If a developer decides to amend commit C that commit's hash gets changed, for instance to D. So now GitHub has the commits listed above, but the developer has this locally:

A---B---D  [master]

When the developer pushes to GitHub the push will be refused, because GitHub contains commit C the master branch, but that commit is not present in the developer's branch. To get GitHub to accept the changes, the developer must now force push.

Any time you find yourself force pushing in Git you're probably doing something that should be carefully considered. It should be an occasional action that you only do when you have to, and not part of the "normal" workflow.

Now that GitHub has been forcefully updated to the new commit structure that includes commit D we have the exact same problem when you try to pull updates from GitHub: the copy of the repository on other developers' machines and on your server can't cleanly resolve the pull because they contain commit C, which is no longer present on GitHub.

We can avoid this problem by not modifying shared history. Instead of amending shared commits, consider just adding a new commit. Your history may now contain messages like

  • Add new feature X
  • Oops, fix simple bug in feature X

but that's a small price to pay for not having to deal with branches that have diverged thanks to modified shared history.

Upvotes: 1

Related Questions