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

Closed
AlexeyRaga opened this Issue Jan 10, 2013 · 24 comments

Projects

None yet

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
Contributor
sc68cal commented Jan 10, 2013

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
Member

I would believe that one of the recent changes caused that. Can you provide
some more info: the command you ran, and the full stack trace (available if
you add --debug to your command).

On Thu, Jan 10, 2013 at 6:36 PM, Alexey Raga notifications@github.comwrote:

The master branch doesn't work (Object reference not set) so I downloaded
the #274 #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 the master branch because it throws Object
Reference Not Set both in master and in #274https://github.com/git-tfs/git-tfs/issues/274changeset.


Reply to this email directly or view it on GitHubhttps://github.com/git-tfs/git-tfs/issues/284#issuecomment-12124766.

@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
Member

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
Contributor
sc68cal commented Jan 11, 2013

@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
Contributor

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
Member

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
Contributor
sc68cal commented Jan 13, 2013

Merged #289

@pmiossec pmiossec closed this May 23, 2013
@mfroberg
mfroberg commented Jul 5, 2013

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
Member
pmiossec commented Jul 8, 2013

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
ghost commented Jul 17, 2013

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
Member

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
ghost commented Jul 17, 2013

Running with –d tells me

The name of the local branch will be : FR1-Hotfix-HF3
Git local branch will be :FR1-Hotfix-HF3
Looking for all branches...
Found parent branch : $/DataNow/Windows/Releases/FR1/b.Hotfix
Found C90718 on branch $/DataNow/Windows/Releases/FR1/b.Hotfix-HF3(UHG)
Found root changeset : 90718
Try to find changeset in git repository...
Sep.Git.Tfs.Core.GitTfsException: error: The root changeset 90718 have not be found in the Git repository. The branch containing the changeset should not have been created. Please do it before retrying!!
---> Sep.Git.Tfs.Core.GitTfsException: error: The root changeset 90718 have not be found in the Git repository. The branch containing the changeset should not have been created. Please do it before retrying!!

at Sep.Git.Tfs.Commands.InitBranch.CreateBranch(IGitTfsRemote defaultRemote, String tfsRepositoryPath, IEnumerable`1 allRemotes, String gitBranchNameExpected, String tfsRepositoryPathParentBranch)
at Sep.Git.Tfs.Commands.InitBranch.Run(String tfsBranchPath, String gitBranchNameExpected)
at Sep.Git.Tfs.Commands.Branch.Run(String param1, String param2)

#90718 is the correct root changeset number in TFS.
There is not Git History for this commit because I haven’t manage to “init” the branch yet – or have I completely misunderstood what you want me to verify? (I’m not that familiar with git – I’m a TFS man)

@pmiossec
Member

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
ghost commented Jul 17, 2013
  •      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).
    
    That is exactly what I have done. It has worked fine for other branches made from the Trunk and other child branches. However, in my case the branch I want to init is off another branch, but not the latest changeset of that child branch.

A <- B <- C <- D <- E $/Repository/ProjectTrunk

M <- N <- O $/Repository/ProjectBranch

P <- Q <- R $/Repository/HotfixBranch

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

Changeset 90718 is the root changeset for HotfixBranch
Changeset 89012 is the changeset the branch was created from in TFS (this commit is present in Git)

@pmiossec
Member

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
ghost commented Jul 17, 2013

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
ghost commented Jul 17, 2013

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
Member

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
ghost commented Jul 17, 2013

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

@pmiossec
Member

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