Search code examples
gitlibgit2rugged

Rugged (libgit2) stage for index


Looking at index (following a call to merge_commits between master and a branch), I'm seeing 3 results for the same file,

{:path=>"file.txt", :oid=>"c6fdbacd7400805042668f4ccf70fc1ebbdac361", :dev=>0, :ino=>0, :mode=>33188, :gid=>0, :uid=>0, :file_size=>0, :valid=>false, :stage=>1, :ctime=>1969-12-31 19:00:00 -0500, :mtime=>1969-12-31 19:00:00 -0500}
{:path=>"file.txt", :oid=>"0838a4be16d19278e1e549614ffd2b6759549185", :dev=>0, :ino=>0, :mode=>33188, :gid=>0, :uid=>0, :file_size=>0, :valid=>false, :stage=>2, :ctime=>1969-12-31 19:00:00 -0500, :mtime=>1969-12-31 19:00:00 -0500}
{:path=>"file.txt", :oid=>"4bd2639f786bef1000dad7d59c6779a4e99fb27c", :dev=>0, :ino=>0, :mode=>33188, :gid=>0, :uid=>0, :file_size=>0, :valid=>false, :stage=>3, :ctime=>1969-12-31 19:00:00 -0500, :mtime=>1969-12-31 19:00:00 -0500}

My understanding by looking at the content of each of these is that stage 3 is the most "recent/advanced" change, but can someone explain the concept behind these stages and the numbering? And stage 0 is missing because there are changes in this file that are uncommited?


Solution

  • I'm not familiar with libgit2, but nonzero stages in git index files are meant for dealing with merge conflicts.

    Until the conflict is resolved, there will be up to three entries for a single path name, as described in the gitrevisions documentation:

    A colon, optionally followed by a stage number (0 to 3) and a colon, followed by a path, names a blob object in the index at the given path. A missing stage number (and the colon that follows it) names a stage 0 entry. During a merge, stage 1 is the common ancestor, stage 2 is the target branch’s version (typically the current branch), and stage 3 is the version from the branch which is being merged.

    If the merge conflict is because of a deletion (i.e., file existed in common ancestor but is missing from one branch and modified in the other), there will be only one of stage 2 or 3; if it is because of a creation (file did not exist in common ancestor but was created in both branches) there will be no stage 1 entry. (I'm not sure I have covered all cases of fewer-than-3 entries here.)

    Before you can finish and commit the merge, you must replace the nonzero stage entries with a single stage-0 entry.