Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Writing conflicting git_merge_trees result index? #1567

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
suskin opened this issue May 10, 2013 · 7 comments
Closed

Writing conflicting git_merge_trees result index? #1567

suskin opened this issue May 10, 2013 · 7 comments

Comments

@suskin
Copy link

suskin commented May 10, 2013

Hey guys,

I'm working on implementing a pull-like operation which, on encountering merge conflicts, always writes THEIRS and OURS files to disk for the user to use to resolve the conflicts. After an attempted merge, I'd like to be able to easily record which files are conflicting so that it's easy to complete the merge after the user has intervened, similar to how git handles this situation. What is the recommended way of doing this?

I was expecting to be able to write the result from git_merge_trees to disk to accomplish this, but passing it to git_index_write_tree_to fails because it won't write an index to disk if it contains conflicts. Should I be modifying the index in some fashion before writing it out, or is there another approach I should take?

Thanks for the help.

@arthurschreiber
Copy link
Member

I think you'll have to do it manually.

You can get index entries for your conflicting files using git_index_conflict_get, and then from the index entries you can get the actual blob sha from the entry's oid struct member. And then, you could use git_blob_lookup to get the actual blob and write that out to disk to wherever you want.

I hope this helps you.

@suskin
Copy link
Author

suskin commented May 11, 2013

Thanks for the quick reply! However, I've already figured out how to write the OURS and THEIRS files; that wasn't my question. I'll clarify.

With git, if I run into a merge conflict, the merge doesn't finish. I can see the conflicting files by calling git status. I can resolve the conflicts myself, git add the conflicting files, and then git commit to finish the merge. How do I get the same behavior using libgit2? Is it possible yet?

Right now I'm trying to figure out how to 'save' the state of the merge in progress, and I've been assuming it involves updating the index. Here's what I've tried so far:

  • Write index result of git_merge_trees() using git_index_write_tree_to() - fails because git_index_write_tree_to() won't write an index with conflicts
  • Get the repository's index with git_repository_index(), pass that index into git_merge_trees(), call git_index_write() with the same index - fails with Failed to read index: The index is in-memory only
  • Copy entries from index result of git_merge_trees() into the index from git_repository_index(), using the git_index_add() and git_index_conflict_add() methods, then call git_index_write() on the repository index - the conflicts do not show up when I call git status

I must be missing something - any thoughts?

@revane
Copy link

revane commented Jul 3, 2013

Ever figure this out suskin? I have exactly the same problem.

@ethomson
Copy link
Member

ethomson commented Jul 3, 2013

Sorry for the late reply - but writing git_merge_trees as an index is almost certainly not what you want to do. You want to merge the results into your existing repository index. (Keeps the stat information, and allows some safe modifications to persist through a merge.)

Check out #1007 for more information. This is a PR, it's not merged, so it's probably got plenty of bugs. Note, though, that this is what is shipping in unnamed commercial IDEs to do a merge of branches.

@revane
Copy link

revane commented Jul 3, 2013

Thanks for the info. So I tried copying entries from the merged index into the repo's index with:

for (unsigned int i = 0; i < git_index_entrycount(MergedIndex); ++i) {
    const git_index_entry *entry = git_index_get_byindex(MergedIndex, 0);
    if (git_index_entry_stage(entry) > 0) {
      continue;
    }
    GIT_CALL(git_index_add(RepoIndex, entry));
  }

  // Add all conflicts.
  GitConflictIterator ConflictIterator;
  GIT_CALL(git_index_conflict_iterator_new(&ConflictIterator, MergedIndex));
  for(;;) {
    const git_index_entry *ancestor;
    const git_index_entry *ours;
    const git_index_entry *theirs;
    if (git_index_conflict_next(&ancestor, &ours, &theirs, ConflictIterator) !=
        0) {
      break;
    }
    GIT_CALL(git_index_conflict_add(RepoIndex, ancestor, ours, theirs));
  }

  GIT_CALL(git_index_write(RepoIndex));

Is this the right approach? I realize the problem suskin was having with git status was probably due to not calling git_checkout_index() (right?)

@suskin
Copy link
Author

suskin commented Jul 4, 2013

@revane no; ended up working on some other tasks.

@ethomson thanks! I'll take a look. Do you have an estimate of when it'll be merged in?

@ethomson
Copy link
Member

ethomson commented Nov 5, 2013

You can use git_merge to merge into the working directory and specify conflicting handling (diff3 style file, take theirs, take ours, etc) so I'm going to close this out now! If I misunderstand and you would really like lower-level access to the blended index, feel free to reopen.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants