0

I committed a change to a file and ran git push; the commit was rejected because my branch was behind its remote counterpart. I then ran git pull and it said Merge made by the 'recursive' strategy.. However, it also pulled up my text editor and had me enter a commit message. Why did git automatically generate a commit when I ran git pull? The resulting commit has two parents, but 0 changed files (no changes at all). Now there is a goofy commit on master that says I merged something, but with no real content.

AlexMA
  • 9,842
  • 7
  • 42
  • 64
  • Read this: http://stackoverflow.com/a/34503873/1401351 – Peter Aug 15 '16 at 18:46
  • @Peter So basically I should have rebased? – AlexMA Aug 15 '16 at 18:54
  • Yes, in most workflows prefer "pull --rebase" for small sets of changes that have not been pushed back to some other branch or shared with others, and for which you don't want to record the actual parallel activity. – Peter Aug 15 '16 at 19:50

1 Answers1

2

When you run git pull, git actually runs a command equivalent to git fetch followed by git merge. In this case the merge is non-trivial, though - you have commits on two divergent branches that must be consolidated before the commit is made. For simplicity's sake, git has made a "merge commit" to handle the consolidation while maintaining the correctness of each branch's history.

If maintaining the branches' history is not of importance, this question is likely of interest.

Community
  • 1
  • 1
Conduit
  • 2,675
  • 1
  • 26
  • 39
  • I am still confused about why the commit has no changes, though. – AlexMA Aug 15 '16 at 18:58
  • Nevermind, that question you posted is basically a duplicate of mine, and does explain it. Seems weird to me, but hey ¯\_(ツ)_/¯ – AlexMA Aug 15 '16 at 19:00
  • @AlexMA no file changes, you mean? Not *entirely* sure, but I'll hazard a guess: the files are actually changed in the respective parent commits, not the merge (which just cherry-picks references from the parent commits). No "changed files" = no output, perhaps? – Conduit Aug 15 '16 at 19:02
  • 1
    @AlexMA I usually just avoid `git pull`, personally... Fetching and merging manually tends to avoid enough problems to be worth the extra keystrokes, IMO :) – Conduit Aug 15 '16 at 19:05
  • 1
    If the merge algorithm can merge two parents with no conflicts, then the merge commit needs no content. It's just an object with two parents. – Peter Aug 15 '16 at 19:50
  • @Peter pretty much as I figured, sounds like - thanks for confirming! – Conduit Aug 15 '16 at 19:52
  • @Peter: it's misleading to say "no content": a merge commit, like any commit, is a full snapshot of the entire source tree. In Git, any one commit can be turned into "the source as of that commit" and internally it actually *has* the entire source for that commit. It just usually shares most if not all files with some other commit(s) (and in the case of a truly trivial merge, every file matches with at least one, if not both, parents). (Git does differ from other VCSes here: other VCSes store deltas, and there, the "size" of a commit depends on the change from the previous commit.) – torek Aug 15 '16 at 20:32
  • @torek So essentially the commit shows no changes because - as I surmised - no changes have been made to the files, only to the references contained in the new commit's snapshot, correct? – Conduit Aug 15 '16 at 20:46
  • 1
    @Conduit: yes, more or less. Note that `git show` on a merge shows a *combined diff*; use `git show -m` to show individualized diffs against each parent (usually there's at least one diff from at least one parent, although in somewhat rare cases, including use of squash "merges" which is less rare now that it's a button on GitHub, both diffs will be empty). – torek Aug 15 '16 at 20:50