Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

init-branch doesn't find the correct root changeset #284

Closed
AlexeyRaga opened this Issue · 24 comments

6 participants

@AlexeyRaga

init-branch command doesn't find the correct root changeset in the parent branch so in Git a relatively new branch (just a couple of commits in it) looks like it was created hundrends of changesets ago.

As a result, it looks like not all the changesets are applied to the branch while migrating. For example, files that were deleted from the "parent" branch before the "child" branch was created are found now in the migrated copy of the "child" branch.

Unfortunately I don't know how to provide you with steps to reproduce, but that's what I have in my environment. The results are consistent: different people have done it on different machines at different time and it always finds the same (wrong) changeset as a root one for the specific branch.

Most of the migrated branches have the same problem.

@sc68cal

We recently merged #274 - this may resolve your issue. You will have to build from source, however.

@AlexeyRaga

The master branch doesn't work (Object reference not set) so I downloaded the #274 merge commit.
Didn't work for me in when copying a branch using an existing (previously cloned by 0.16.1) repository.

BTW, I cannot re-migrate my sources from scratch because "git-tfs clone" throws Object Reference Not Set or "The given key was not present in the dictionary" both in master and in #274 changeset.

The latest version is actually failing on the following line:

branchTrees[branch.ParentPath].ChildBranches.Add(branch);

It is probably a heritage of out long history with TFS (2005->2008->2010, branches were moving, etc).
Because the branch it did not like was a very antique one I just guarede this code with "if":

if (branchTrees.ContainsKey(branch.ParentPath))
    branchTrees[branch.ParentPath].ChildBranches.Add(branch);  

Will let you know if the latest version will be able to identify the root changeset correctly.

@spraints
Owner
@AlexeyRaga

Well I have tracked the issue down (the original one, about wrong parent root changeset).
I appears to be in the TfsHelperVs2010Base.GetRootChangesetForBranch function.
Here is what I change to make it work:

var mergedItemsToFirstChangesetInBranchToCreate =
     VersionControl.TrackMerges(new int[] {firstChangesetInBranchToCreate.ChangesetId},
                                       new ItemIdentifier(tfsPathBranchToCreate),
                                       new ItemIdentifier[] {new ItemIdentifier(tfsPathParentBranch),},
                                       null)
                  .OrderBy(x => x.SourceChangeset.ChangesetId);

What was missing is the

.OrderBy(x => x.SourceChangeset.ChangesetId);

line.

It appears to be that TrackMerges returns changesets in a strange order (however deterministic).
So when I do .LastOrDefault() in my situation I get some semi-random changeset Id.

Please consider to change the code in the repository if you think it is beneficial :)

@spraints
Owner

Sounds good. Do you have a couple of minutes to create a pull request with this change?

@AlexeyRaga

OK, I'll do it tomorrow.

@sc68cal

@davidalpert & @AlexeyRaga may want to discuss this, since it relates to the work @davidalpert has done in davidalpert/git-tfs@a7653ba

@AlexeyRaga

I'll have to test @davidalpert's change once I have access to TFS after the weekend. Off the top of my head I'd say that there can be more than one changesets satisfying the condition @davidalpert introduced (and perhaps that's why it is LastOrDefault, not SingleOrDefault). And it is not clear to me how TFS orders these changesets and if this "default" order (therefore LastOrDefault) is reliable.

Suggested tests:

  1. Create a branch in TFS, add a set of commits to both parent and child branches, migrate to Git with init-branch.
  2. Create a new branch in TFS from an "old" existing changeset, make some commits, migrate to Git with init-branch.

In both cases ensure that the branching point is migrated correctly.

If possible (or if any of you, guys, know) it would be helpful to figure out how TFS API determines the order of the results returned by TrackMerges.

@davidalpert
Collaborator

off the top of my head Ordering by Changeset ID seems practical, as from what I can tell TFS always increments ChangesetID in a predictable way across a given repository, though not tied to a given project.

The trackmerges and finding root branch code is a merge of my changes and many from @pmiossec so let's bring him in on this also.

@pmiossec
Owner

I also thought that the changeset were returned in the good order because, for me, the changeset ID is an incremented index key.
But if @AlexeyRaga have this problem, surely, it is not. Nothing really surprise me when it come from TFS...
Perhaps due to TFS version migration.
Anyway, if order the collection correct the problem, let's do it!
@sc68cal In fact, the @davidalpert version davidalpert@a7653ba should not work well to test the init-branch :( Should merge #289 before...

@sc68cal

Merged #289

@thomaswurtz thomaswurtz referenced this issue from a commit
Commit has since been removed from the repository and is no longer available.
@pmiossec pmiossec closed this
@mfroberg

I have the original problem, in a git tfs built from master at 8e6bfc3.

error: The root changeset 246256 have not be found in the Git repository. The branch containing the changeset should not have been created. Please do it before retrying!!

The root changeset (246256) is on the targeted branch, i.e. the branch I am trying to init.

I have debugged and isolated the problem to TfsHelperVs2010Base.GetRootChangesetForBranch. From what I can see the problem is in the call to VersionControl.TrackMerges, which I currently don't know how it works.

I will continue to debug and learn about the code.

Anything specific I should check?

Its quite possible I have done something wrong in the git-tfs compile, but I don't think so.

@pmiossec
Owner

Strange... Are you sure that the branch you cloned was your master branch and the the one you init is the child branch?
VersionControl.TrackMerges() is a method which return the merge points (changesets) on a branch.

Its quite possible I have done something wrong in the git-tfs compile, but I don't think so.

No, should not be the problem.

@ghost

I am also seeing the same problem.
I have a branch in TFS that I have created from an earlier changeset in the parent branch e.g. not branched from the latest changeset. When I try to init the branch I get the same error as above "the root changeset have not ben found..." etc.

I'm using 0.17.2

I'll try and find out if it is the same problem

@pmiossec
Owner

Just to verify... if you run the command in debug mode ( with -d option), it give you the root changeset it try to find. Verify if there is a git commit corresponding in your git history. And if that's the real root changeset and at what it correspond in the TFS history...

@ghost
@pmiossec
Owner

hum... your answer make me understand that you miss something :(

If we have something looking like that in TFS :

A <- B <- C <- D <- E  $/Repository/ProjectTrunk
           \                              
            M <- N     $/Repository/ProjectBranch

With git-tfs, you can clone either $/Repository/ProjectTrunk or $/Repository/ProjectBranch and you will end with only the cloned branch in your repository.

BUT if you want to manage branches, that's not the thing that you should do.

If you want to manage branches, you must clone the rot branch $/Repository/ProjectTrunk and then init the $/Repository/ProjectBranch branch (and other branches if you have others).

If that's what you did, when you try to init the branch $/Repository/ProjectBranch the root changeset B (for you 90718) should already have been in you git repository (because fetched when you cloned the rot branch).

And if a branch is dependent of another branch, you should init the parent branch before!
At the moment, git-tfs don't manage branch dependency except if you use the flag --all (but in this case, you will init all the branches)

To summerize, with git-tfs, you should clone your trunk and the init-branch command is a way to add a branch to you git DAG (tree of commits).

More help here :
https://github.com/git-tfs/git-tfs/blob/master/doc/commands/init-branch.md#examples

@ghost
@pmiossec
Owner

I have successfully run init-branch on “ProjectBranch” and I am having problems when trying to init “HotfixBranch”

Ok. So...Have you, or not, a git commit corresponding to the changeset 90718 in your parent branch $/Repository/ProjectBranch?

The root changeset is the last changeset in common and should be in the parent branch (and, thus, already fetched and already in your git repository). If that's not the case, there is a real problem...

@ghost

No. Changeset 90718 (item "P" on the diagram above) is on HotfixBranch and does not exist in Git.

Changeset 89012 (item "N" on my diagram) is the last changeset in common and is on the parent branch - this does exist in Git

branch

@ghost

Ahh. I forgot one small bit. After I created the branch in TFS, I renamed it. Could that be the problem?

89012 is the common root, 90643 was created from this and then the branch was renamed and 90718 is the first changeset on the renamed branch.

@pmiossec
Owner

I think you found the problem. git-tfs do not support renames :(
And you just discover that internaly, the way TFS store changes are sometimes a real pain :(

I think you should create a new issue describing the problem (manage branch rename in init-branch...)

As I am the developper of this command, I suppose I will be the one that will correct it but I have no time now and in the near future. I can't tell you now when I will fix it (and I should create a test case to debug the problem.....)

@ghost

OK. I'll create an issue. Thanks for being so quick with the responses!

@pmiossec
Owner

Your welcome. It's always a pleasure to help someone run away TFSVC ;)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.