Git Product home page Git Product logo

Comments (5)

jacquesg avatar jacquesg commented on June 7, 2024

Well, merge works with references, not commits. You cannot do this:

my $id = $refs->{$ref}->{'id'};
my $merge_source = $self->repository->lookup($id);

You need to perform a lookup of the references, that is:

my $merge_source =  $self->repository->lookup($ref);

An example of how to do this is captured in t/15-merge.t. The correct way to do this is to do a merge_analysis first though. If it tells you that the merge is fast-forward, you don't really want to do a merge, just fast-forward the reference and/or HEAD to the commit of the ref you're trying to merge.

from p5-git-raw.

jacquesg avatar jacquesg commented on June 7, 2024

Excerpt from the test file:

$repo -> checkout($repo -> head($master), {
    checkout_strategy => {
        'force' => 1
}});

my $branch3 = $repo -> branch('branch3', $initial_head -> target);
my $r = $repo -> merge_analysis($branch3);
is_deeply $r, ['normal'];

$repo -> merge($branch3, {
    'favor' => 'theirs',
    }, {
    checkout_strategy => {
        'safe_create' => 1
    }
});

from p5-git-raw.

sedninja avatar sedninja commented on June 7, 2024

Thanks @jacquesg! I had to do a little massaging to get a successful merge of fetched changes, but I can now see the working directory being updated. Here is what I have so far:

sub pull {
    my ( $self, $remote, $target_branch ) = @_;
    if ( not $remote ) {
        $remote = "origin";
        $target_branch = "devel";
    }
    my $rem = $self->remote($remote);
    my $branch = $self->get_branch($target_branch);
    $rem->callbacks({ 
        credentials => sub { $self->{_cred} },
        update_tips => sub {
            my ( $ref, $a , $b ) = @_;
            $self->log('debug',"Updated: %s ( %s -> %s )",$ref,$a,$b);
        }
    });
    $rem->fetch();
    my $refs = $rem->ls;
    my $pat = qr|^refs/heads/($target_branch)$|;
    foreach my $ref ( keys %{$refs} ) {
        if ( $ref =~ $pat ) {
            my $id = $refs->{$ref}->{'id'};
            my $success = try {
                $ref =~ s|$pat|refs/remotes/$remote/$1|; 
                my $merge_source = Git::Raw::Reference->lookup($ref,$self->repository);
                my $anal = $self->repository->merge_analysis($merge_source);
                my $ff = grep { /fast_forward/ } @{$anal};
                my $mopt = { favor => 'theirs' };
                my $copt = { checkout_strategy => { safe_create => 1 }};
                my $merge = $self->repository->merge($merge_source,$mopt,$copt);

                if ( not $ff ) {
                    $self->log("debug","merging %s into current HEAD",$id);
                } else {
                    $self->log("info","updating HEAD to $id using fast-forward");
                }
                $self->log("trace",Dumper $merge);
                return $id;
            } catch {
                $self->log('crit',"failed to merge %s: %s",$ref, $_->message);
                return undef;
            };
            $self->log('warn',"merger of upstream changes was unsuccessful due to one or more errors") if not $success;
        } else {
            $self->log("info","Not analyzing $ref");
        }
    }
    $rem->disconnect;
    return $rem;
}

Now the test repo I am using has 1 file which was added in a previous test but is not part of the initial repo that is being cloned to create the working copy. I can see the file being pulled into the directory, and I am receiving fast_forward from the analysis, but the merge return value is undef which is not what I would expect. I also have a normal item in the analysis results so I think that Git::Raw::Repository::merge is defaulting to a recursive merge instead of fast-forward. Is there any way to suggest the fast-forward if possible? I don't see any flags or merge_options to set the preference.

Also, since I am not doing a fast forward, it seems like I will need to commit the changes in order to be able to push to another (separate) remote. Am I understanding this correctly?

from p5-git-raw.

jacquesg avatar jacquesg commented on June 7, 2024
  1. The reason you get undef from merge is because it doesn't return anything, see: https://metacpan.org/pod/Git::Raw::Repository#merge-ref-merge_opts-checkout_opts
  2. If the merge is fast-foward, no merge is performed (its not necessary), you need to update the ref that you're trying to merge into with something like $ref->target($new_commit_id). IMPORTANT: This doesn't update the index or necessarily HEAD for you.
  3. If the merge is not fast-forward, the index will be updated for you. What you need to do is resolve conflicts (if any), and then create a merge commit (a commit with more than 1 parent). Typically the merge commit's parents would be the id of the tip of branch you're merging into, and the tip of the branch you're merging.

libgit2 and Git::Raw are plumbing, you need to implement you're own porcelain 😄

from p5-git-raw.

jacquesg avatar jacquesg commented on June 7, 2024

Here is an excerpt from t/15-merge.t that shows the creation of the merge commit: NOTE, $index->write_tree() now returns a Git::Raw::Tree object (on master), you're version probably only returns an id which you need to use to lookup the tree.

is $index -> has_conflicts, 0;
$repo -> merge($branch2);
is $index -> has_conflicts, 1;

write_file($file1, 'this is file1 on branch1 and branch2');
$index -> add('test1');
$index -> write;

my $merge_msg = $repo -> message();
is $merge_msg, "Merge branch 'branch2'\n\nConflicts:\n\ttest1\n";

my $target = $master -> target;
$commit = $repo -> commit("Merge commit!", $me, $me, [$target, $commit2],
    $index -> write_tree);

from p5-git-raw.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.