Visitar URL original
`Repository.mergeBranches` creates dirty index after a non-conflicting merge · Issue #1217 · nodegit/nodegit · GitHub
Skip to content

Repository.mergeBranches creates dirty index after a non-conflicting merge #1217

Description

@rcjsuen
  1. Run the code below.
  2. You will see that stuff gets printed indicating a dirty index.
  3. cd merge-commit-bug
  4. git status
> git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

        modified:   test.txt

All the tests in merge.js merges two random branches so the bug doesn't appear. The bug will only surfaces if you merge HEAD with another branch.

var path = require("path");
var fs = require("fs");
var git = require('.');
var repoDir = path.resolve(__dirname, "merge-commit-bug");
var name = "test.txt";
var name2 = "test2.txt";
var fileName = path.resolve(repoDir, name);
var fileName2 = path.resolve(repoDir, name2);
var repository;
var index;
var head;
var leftBranch;

return git.Repository.init(repoDir, 0)
.then(function(repo) {
	repository = repo;
	fs.writeFileSync(fileName, "A", null);
	return repository.refreshIndex();
})
.then(function(idx) {
	index = idx;
	return index.addByPath(name);
})
.then(function() {
	return index.writeTree();
})
.then(function(oid) {
	return repository.createCommit("HEAD",
		git.Signature.default(repository),
		git.Signature.default(repository),
		"message", oid, []);
})
.then(function(oid) {
	head = oid;
	fs.writeFileSync(fileName, "B", null);
	return repository.refreshIndex();
})
.then(function(idx) {
	index = idx;
	return index.addByPath(name);
})
.then(function() {
	return index.write();
})
.then(function() {
	return index.writeTree();
})
.then(function(oid) {
	return repository.createCommit("HEAD",
		git.Signature.default(repository),
		git.Signature.default(repository),
		"left", oid, [ head ]);
})
.then(function(left) {
	return repository.getCommit(left);
})
.then(function(commit) {
	return git.Branch.create(repository, "leftBranch", commit, false);
})
.then(function(branch) {
	leftBranch = branch;
	return repository.getCommit(head);
})
.then(function(commit) {
	return git.Reset.reset(repository, commit, git.Reset.TYPE.HARD, {});
})
.then(function() {
	fs.writeFileSync(fileName2, "C", null);
	return repository.refreshIndex();
})
.then(function(idx) {
	index = idx;
	return index.addByPath(name2);
})
.then(function() {
	return index.write();
})
.then(function() {
	return index.writeTree();
})
.then(function(oid) {
	return repository.createCommit("HEAD",
		git.Signature.default(repository),
		git.Signature.default(repository),
		"right", oid, [ head ]);
})
.then(function(commit) {
	return repository.mergeBranches("master", leftBranch, git.Signature.default(repository), null, null);
})
.then(function() {
	return repository.getStatus();
})
.then(function(statuses) {
	console.log(statuses);
	console.log(statuses[0].path());
})
.catch(function(err) {
	console.log(err);
});

Activity

  1. raqqun commented on Feb 18, 2017

    @raqqun

    Unfortunately i'm having the exact same problem.

    The code below produces a merge and a commit with message "Merged master into dev".
    But then when i'm doing a git status i'm getting :

    On branch dev
    Your branch is ahead of 'origin/dev' by 156 commits.
      (use "git push" to publish your local commits)
    Changes to be committed:
      (use "git reset HEAD <file>..." to unstage)
    
            modified:   .gitignore
    	modified:   license.txt
    	modified:   readme.html
    	modified:   wp-activate.php
    	modified:   wp-admin/about.php
    	modified:   wp-admin/admin-ajax.php
            .....

    which is odd since the merge produced earlier has the files committed.

    I'm using the code below to fetch origin and merge the two branches.

        NodeGit.Repository.open(path).then(function(repoResult) {
            repo = repoResult;
        })
        .then(function() {
            repo.fetch('origin', {
                callbacks: {
                    credentials: function(url, userName) {
                        return NodeGit.Cred.sshKeyMemoryNew(userName, publickey, privatekey, '');
                    }
                }
            })
        })
        .then(function() {
            return repo.mergeBranches('dev', 'master');
        })
        .catch(function(err) {
            console.log(err);
        });
  2. rcjsuen commented on Feb 19, 2017

    @rcjsuen
    MemberAuthor

    @raqqun I suppose you could try working around the problem by switching your HEAD to point elsewhere and/or by performing a hard reset after the merge.

  3. neloe commented on May 17, 2017

    @neloe

    I am having this same problem; if I merge a branch into master, the merge works (the commit is there, and it is appropriate). After the merge, git status shows that I have uncommitted (but staged) changes; these changes would undo the previous commit. The problem with a hard reset after the merge is that it might clobber other staged (but uncommitted) changes. I need to play around with git itself to see what it does in this situation.

    I'll try moving HEAD around and see what that does.

    This is snippets of the code that's exhibiting this behavior (with the reset in there). Unfortunately, this clobbers my staged and/or unstaged changes from already tracked files.
    https://gist.github.com/neloe/cb486f73d73a34f7e890d7c827483c54

  4. Nard-Dog commented on Jun 1, 2017

    @Nard-Dog

    Seeing the same issue with nodegit v0.19.0 and git v2.6.2

    Steps to reproduce:

    1. Checkout a branch
    2. Edit a file
    3. Refresh Index
    4. Add all to the index
    5. Create a commit
    6. Push commit to remote
    7. Checkout other branch
    8. Merge first branch into other branch
    9. Push to remote.

    Expected:
    git status should show that I have a clean index and no staged changes.

    Actual:
    git status reads that I have staged changes which would negate the ones I just committed.

  5. kryp71c commented on Sep 21, 2017

    @kryp71c

    I had a similar issue. What worked for me was using the example from https://github.com/nodegit/nodegit/blob/master/examples/add-and-commit.js
    which adds a couple of steps between writeTree and createCommit:

    .then(function() {
      return index.writeTree();
    })
    .then(function(oidResult) {
       oid = oidResult;
       return nodegit.Reference.nameToId(repo, "HEAD");
    })
    .then(function(head) {
       return repo.getCommit(head);
    })
    .then(function(parent) {
      return repository.createCommit("HEAD",
        git.Signature.default(repository),
        git.Signature.default(repository),
        "right", oid, [ parent ]);
    })
  6. lal12 commented on Nov 22, 2021

    @lal12

    I had a similar issue. In my case the issue was that I fetched refs/heads/master:refs/heads/master instead of refs/heads/master:refs/remotes/origin/master.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions