Skip to content
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

Moved files show up in deltas as two entries #1116

Open
martinheidegger opened this issue Sep 2, 2016 · 5 comments
Open

Moved files show up in deltas as two entries #1116

martinheidegger opened this issue Sep 2, 2016 · 5 comments

Comments

@martinheidegger
Copy link
Contributor

martinheidegger commented Sep 2, 2016

If you move a file it is recognized as one operation with clients such as Sourcetree:

https://gyazo.com/100c0d8948b030b8b564f67a70f6d95a

but if I check diffDelta's with nodegit like this:

commit.getDiff()
  .then(function (diffs) {
    // note: I am not sure why this I an Array?! It seems to always have only one entry?
    for (var diffNr = 0; diffNr < diffs.length; diffNr++) {
      var diff = diffs[diffNr]
      var deltas = diff.numDeltas()
      for (var i = 0; i < deltas; i++) {
        var delta = diff.getDelta(i)
        console.log(delta.newFile().path(), '←', delta.oldFile.path())
      }
    }
  })

i get the output:

test/data/renamed/test-a.json ← test/data/renamed/test-a.json
test/data/renamed/test.json ← test/data/renamed/test.json

Which is weird because the API obviously says oldFile.path() but it just shows the two delta's separately?!

The only workaround I can see to fix this in my code is to compare every delta in the diff with the file I am looking for an see whether its the same file (to see whether it was a "move")

@martinheidegger
Copy link
Contributor Author

Further research revealed following workaround:

commit.getDiff()
 .then(function (diffs) {
    for (var diffNr = 0; diffNr < diffs.length; diffNr++) {
      var diff = diffs[diffNr]
      var deltas = diff.numDeltas()
      for (var i = 0; i < deltas; i++) {
        var delta = diff.getDelta(i)
        for (var j = 0; j < deltas; j++) {
          if (j !== i) {
             // Note: the documentation of `.cmp` is rather thin. For some queer reason `.tostrS` seems to work too....
             var otherDelta = diff.getDelta(j)
             if (otherDelta.oldFile().id().cmp(delta.newFile().id()) === 0 /* why 0? */) {
                // oh! this file has moved!
                console.log(otherDelta.newFile().path(), '←', delta.oldFile().path())
                return
             }
          }
        }
        console.log(delta.newFile().path(), '←', delta.oldFile.path())
      }
    }
  })

Which is quirky and weird - to say the least.

@rcjsuen
Copy link
Member

rcjsuen commented Feb 21, 2017

@martinheidegger Maybe try "compressing" your diff with the findSimilar function.

var git = require(".");
var repo_dir = "tmp";
var repo;
var diff;

git.Repository.open(repo_dir)
.then(function(_repo) {
  repo = _repo;
  return repo.getHeadCommit();
})
.then(function(c) {
  return c.getDiff();
})
.then(function(d) {
  diff = d[0];
  var opts = {
    flags: git.Diff.FIND.RENAMES
  };
  return diff.findSimilar(opts);
})
.then(function() {
  console.log(diff.numDeltas());
  var delta = diff.getDelta(0);
  console.log(delta.status() === git.Diff.DELTA.RENAMED);
})
.catch(function(err) {
  console.log(err);
});

@rcjsuen
Copy link
Member

rcjsuen commented Feb 21, 2017

As to your question in your code's comment, getDiffs is returning an array because the diff is performed against the commit's parent. Most commits usually have one parent so there is usually only going to be one entry. However, if a commit is a merge commit, then it will have two (or more?) parents and then it will return individual diffs against each parent when getDiffs is called.

@wmertens
Copy link
Contributor

@rcjsuen what is the standard way to show diffs from two parents? Is there a way to combine the diff? Or is it better to show diffs from both sides separately?

@wmertens
Copy link
Contributor

wmertens commented Mar 3, 2021

self-answer: convention is to show the diff vs the leftmost parent. For stashes you need to add to that the stand-alone diff of the second parent, which contains untracked files

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

3 participants