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
Update TfsHelper.Common.cs' detection of the branch point changeset f… #973
Conversation
…or a given path to support scenarios where the branch point isn't the first changeset; update GitTfsRemote to support setting InitialChangeset externally; update InitBranch to handle setting tfsRemote.InitialChangeset when a given branch's actual branch point is specified instead of assumed. This fixes issue git-tfs#955 for sure - I had the same issue.
Oh, I should add - |
AppVeyor automated build failed on chocolately's install of tfs2010objectmodel. I'm not sure how to help with that. |
Oh ! shiny! That's the contribution I have waited too long.... I have relaunched the appveyor build and it is now failing on a real problem :-( We are using paket on this project. Perhaps, instead of using nuget, perhaps just update the xunit runner version in 'paket.references' file and do a |
Ah! I've never before used paket; sure - I can update that. Thanks for pointing me in the right direction. |
I think I've got the NuGet -> paket fixes in place but AppVeyor is timing out again. |
I have relaunched the build but it fails again :-(
I don't know the exact problem, surely your fix that is not complete but I
think I can have a deeper look and fix that... (soon).
I let you know...
|
Oh, it's more than possible I've missed something with this build process - I'm not at all familiar with many parts of this solution's build process :) |
I think you did well, once you know we use paket. That's just that you have also to revert the changes made by nuget to the |
Since the build with AppVeyor was introduced, we never had the problem with restauring the chocolatey packages ( here the tfs2010objectmodel). We will see how it behave in the futur but I really think to remove build for TFS2010 (or make it in another independant build....) cc @spraints |
@jeremy-sylvis-tmg Build failed. I didn't understand what you tried to do :( and reset to this commit if you want ;) |
Well, I'd reverted the changes from NuGet and performed the .paket/paket.exe install - it looks like the build's still failing with paket's changes to the .csproj. More specifically, it looks like paket is just modifying the .csproj to reference the nuget packages through paket. It looks like I'm going to need to leave the .csproj untouched entirely. Any idea why paket might be trying to reference the NuGet package that I'm trying to not depend on? |
… build is failing to compile though local compilation succeeded and ReSharper is suggesting removing the redundant private setter
Well, AppVeyor succeeded but TeamCity is running into what appears to be an issue stemming from a lack of private setters on a few properties. I've corrected that. It's odd that local builds succeed, appveyor's build/tests succeed, but TeamCity's build fails. |
Excellent... looks like that did it. All yours, @pmiossec |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've reviewed this code. In short, I can't wait to see these changes make it into the Git-TFS code base.
I have however, made, a lot of my comments around unnecessary reformatting and whitespace changes that made it take longer for me to review this code.
I also found two significant concerns: A renamed public interface method, and the addition of an interface property that in one implementing class throws an exception for both the getter and setter.
Lastly, I personally would appreciate if you would rebase your commits and reword your commit messages such that they follow Git good commit message guidelines. This is just one article, but I have 5 more bookmarked that are very similar, if not identical in nature--so these are fairly strong guidelines that ought not to be ignored and makes browsing repository history much easier--especially when running a git log --one-line
command.
Other than that, excellent work in helping resolve this long outstanding problem with Git-TFS. I myself wanted to look into this but didn't have the time to dedicate to it, as I've been working on a project for Git for Windows, so Thank You for this PR!!
|
||
string renameFromBranch; | ||
var rootChangesetInParentBranch = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Generally it's considered bad form to reformat code. For example, perhaps this project has some "line-length" policy with respect to their source code formatting? Also, it just adds extra noise to the Pull Request that reviewers have to look at that detracts from the main point of the Pull Request.
More likely, the reason why the code was formatted the way it was is because when reviewing Pull Requests, the lines of code fit nice and neatly in the amount of space provided by GitHub. Now I have to horizontally scroll over to the right to see what's hanging off the edge.
Please revert all code re-formatting so that it fits nicely in the GitHub source code review pane.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Most of the reformatting, renaming, and/or refactoring I'd performed was in order to add clarity where it was lacking and to make it easier to understand what's going on.
I've got exceptionally limited available time to work on this, but thank you for the guidance on Git commit messages.
I'll address what I can but my concern in fixing this issue was fixing broken functionality, as opposed to preserving whitespace & formatting.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree, refactoring in a pull request that add a feature or fix a bug is a bad idea (that could just achieve the goal to delay the PR merge :( )
But now that it's done, no need to undo. It's fine...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@pmiossec: You mentioned in your review below about the change in name for this variable and wanting the rename change reverted. Based on the nature of the changes being made, I think a name change may be warranted to clarify what exactly is now happening in this region of code. I opposed the reformatting of the line breaks that were made--but not necessarily the name change.
Of course, you're the maintainer and may have other reasons for not wanting to change this name, so I'll defer to your judgement. But I just wanted to be clear about what I opposed with respect to this particular diff and also be supportive of why a name change may not be such a bad thing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't have a strong advice on that naming and don't really know which is the best. Keep it that way if you feel that's better...
Trace.WriteLineIf(renameFromBranch != null, "Found original branch '" + renameFromBranch + "' (renamed in branch '" + tfsPathBranchToCreate + "')"); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Generally, it's considered bad form to add/remove existing whitespace (unless fixing an obvious whitespace issue, like a space hanging off the end of a line--but then, only sparingly) for some of the same reasons that it's bad form to reformat existing code. In this case, the primary reason being that it adds noise to the PR and requires extra effort for reviewers.
@@ -516,28 +565,30 @@ public override string ToString() | |||
} | |||
} | |||
|
|||
private IEnumerable<MergeInfo> GetMergeInfo(string tfsPathBranchToCreate, string tfsPathParentBranch, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please un-reformat.
{ | ||
var mergedItemsToFirstChangesetInBranchToCreate = new List<MergeInfo>(); | ||
var merges = VersionControl |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please un-reformat.
new ItemIdentifier(tfsPathBranchToCreate), | ||
new ItemIdentifier[] { new ItemIdentifier(tfsPathParentBranch), }, | ||
null) | ||
.OrderByDescending(x => x.SourceChangeset.ChangesetId); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To be clear, I like these whitespace changes, personally. But it would've been better to have a commit soley dedicated to whitespace changes that I could ignore when reviewing since they don't affect the execution of the code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a fair point - I'll keep it in mind in the future. Most of the whitespace changes were automatically performed by ReSharper as I went through; I'll have to keep an eye on it.
@@ -695,10 +703,17 @@ private void quickFetch(ITfsChangeset changeset) | |||
private IEnumerable<ITfsChangeset> FetchChangesets(bool byLots, int lastVersion = -1) | |||
{ | |||
int lowerBoundChangesetId; | |||
|
|||
// If we're starting at the Root side of a branch commit (e.g. C1) but there are invalid commits between C1 and the actual branch-side of the commit operation |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be helpful if each comment line fit within the line-length for a GitHub pull request code file review pane.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm sure it would... but that also means roughly 2/3 of a 1080p display is wasted when editing source through Visual Studio.
It feels like trying to fix a problem by treating a symptom (line width) rather than the problem (poor code review layout in GitHub).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's actually to help others to be able to quickly review and understand the code without needing to scroll horizontally (which is a huge pain in the butt). While you may have a wide display, not everyone does. In addition, GitHub limits the length of lines shown in PR code reviews, so even if you and I have wide displays, they're virtually useless when reviewing a PR here on GitHub.
Wide monitors are great for watching movies and gaming--not so much for coding (in trems of long line lengths). They are also great for being able to view multiple source files side-by-side...but beyond that, not really useful in code files in and of themselves.
@@ -16,7 +16,7 @@ public interface IGitRepository : IGitHelpers | |||
IGitTfsRemote ReadTfsRemote(string remoteId); | |||
IGitTfsRemote CreateTfsRemote(RemoteInfo remoteInfo, string autocrlf = null, string ignorecase = null); | |||
void DeleteTfsRemote(IGitTfsRemote remoteId); | |||
IEnumerable<string> GetGitRemoteBranches(string gitRemote); | |||
IEnumerable<string> GetGitRepositoryBranchRemotes(string gitRemote); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why the method name change? You're changing an interface contract that others may depend upon, potentially breaking 3rd party libraries that build on top of Git-TFS.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Clarity, essentially.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wouldn't change this method name--it's on an interface. Do you know who's all implementing this interface? Is it only Git-TFS libraries that implement this interface? You can't be sure, because the interface is public
.
I really think this needs to be reverted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, revert the rename, please...
@@ -48,6 +48,7 @@ public interface IGitTfsRemote | |||
string Prefix { get; } | |||
bool ExportMetadatas { get; set; } | |||
Dictionary<string, string> ExportWorkitemsMapping { get; set; } | |||
int? InitialChangeset { get; set; } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Based on comments I made above for this property, I think this is better off being a method on the interface. Please change this to a method pair: GetInitialChangeset()
and SetInitialChangeset(int?)
. This way, you can document under what conditions these proposed methods will throw a DerivedRemoteException
exception.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree - I think I'd gone with the property out of sheer frustration and desire to just expose the needed information. It should have been a method pair.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It should have been a method pair
Minor correction: It should be a method pair
Please change this and update the pull request.
get { return string.Format("{0} C{1}{2}", TfsBranchPath, RootChangeset, (IsRenamedBranch ? " renamed" : "")); } | ||
get | ||
{ | ||
if (TargetBranchChangesetId > -1) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, properties shouldn't do much computation or logic. They should simply return some value. Since you added some conditional logic here, it might be better to extract a private method from the getter here and return the result from the newly extracted method. What are the chances this logic may be needed elsewhere?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the chance of this logic being needed elsewhere is slim. On one hand, I agree that a property shouldn't do computation or logic. On the other hand, we'd then be adding a private method for the sole purpose of building a string exposed by a property. They feel equally wrong to me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's actually a good thing. I'm not going to say that this has to be done, but it's definitely something I would strongly advocate for.
//Ensure our Branch was migrated... | ||
Assert.NotNull(branch); | ||
|
||
// So, it turns out GetRootChangesetForBranch is really the unit under test here. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, maybe you could create a Test Spy or some other kind of "test double" to help you assert/verify the behavior you're expecting?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had considered it.
The larger problem is that the unit under test isn't the appropriate one; we could test the integration of Clone and InitBranch easily enough using a spy/stub via Moq, but the logic we're actually concerned with is in InitBranch, TfsHelper, DerivedGitTfsRemote, GitTfsRemote, and RootBranch.
I would have loved to test-drive these changes but didn't (and don't) have the time necessary to build missing test coverage, especially given the necessary refactoring with buried dependencies, singletons, etc. This was my compromise - a test added to the existing layer illustrating what we're going for with a warning for future developers.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yikes...hmm.. Yeah, seems like a concept is missing and is now looking to be extracted out and become its own thing--which is not a trivial thing to accomplish. Well, at least it's documented. 😄
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We know that there a lot of things that could be improved in our tests.
We are fine with these type of integration tests because the cases that we want to tests are difficult to build with pure unit tests :(
You could keep the test like that.
@pmiossec, @spraints I'm very interested in seeing this PR make it into the code base. I have left a review and was wondering if you had any further observations? I'd also be interested in overall feedback on my feedback (meta-feedback? 😉) to help me learn what you expect of code contributions (beyond what's documented in the |
I am also very interested by that (even if I couldn't find the time to do a proper review until now!). First of all, I mostly agree with what @fourpastmidnight wrote in the review... @jeremy-sylvis-tmg I think @fourpastmidnight told you weel but I will say it myself. When we do a PR, like , that's better to do NO refactoring (moving code, renaming, fix white spaces,...) to easy the code review. Could you also take some time rebase all your work onto No need to worrie too much for the formatting in this PR (even if in normal time we should do) because I plan to use CodeFormatter ( https://github.com/dotnet/codeformatter ) after that PR merged to clean a lot of things... Let's go begin the review ;) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you could rebase the PR and fix most of the things, I will be pleased to merge this pull request.
Thanks a lot again for the hard work! 👍
@@ -98,6 +98,13 @@ | |||
<WCFMetadata Include="Service References\" /> | |||
</ItemGroup> | |||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> | |||
<Choose> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please revert all the changes of this files. Blame paket but there is just noise here :(
@@ -40,9 +40,6 @@ | |||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors> | |||
</PropertyGroup> | |||
<ItemGroup> | |||
<Content Include="app.config.install.xdt"> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please revert all the changes of this files. That's tricky but the explaination is here: https://github.com/git-tfs/git-tfs/blob/master/doc/paket.md#when-adding-a-new-package
@@ -1,33 +0,0 @@ | |||
<?xml version="1.0" encoding="utf-8"?> | |||
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform"> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Again, revert this change...
|
||
string renameFromBranch; | ||
var rootChangesetInParentBranch = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree, refactoring in a pull request that add a feature or fix a bug is a bad idea (that could just achieve the goal to delay the PR merge :( )
But now that it's done, no need to undo. It's fine...
@@ -76,6 +76,8 @@ public int Run(string tfsBranchPath, string gitBranchNameExpected) | |||
|
|||
if (CloneAllBranches) | |||
{ | |||
// TODO: Remove this! | |||
//Debugger.Launch(); | |||
return CloneAll(tfsBranchPath); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're right!! Please remove this comment ;)
@@ -155,7 +155,7 @@ private IGitTfsRemote ReadTfsRemote(string tfsUrl, string tfsRepositoryPath) | |||
} | |||
} | |||
|
|||
public IEnumerable<string> GetGitRemoteBranches(string gitRemote) | |||
public IEnumerable<string> GetGitRepositoryBranchRemotes(string gitRemote) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure I like this rename, too... we are in the repository so no need to add it in the name.
@@ -16,7 +16,7 @@ public interface IGitRepository : IGitHelpers | |||
IGitTfsRemote ReadTfsRemote(string remoteId); | |||
IGitTfsRemote CreateTfsRemote(RemoteInfo remoteInfo, string autocrlf = null, string ignorecase = null); | |||
void DeleteTfsRemote(IGitTfsRemote remoteId); | |||
IEnumerable<string> GetGitRemoteBranches(string gitRemote); | |||
IEnumerable<string> GetGitRepositoryBranchRemotes(string gitRemote); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, revert the rename, please...
<When Condition="($(TargetFrameworkIdentifier) == '.NETStandard' And ($(TargetFrameworkVersion) == 'v1.0' Or $(TargetFrameworkVersion) == 'v1.1' Or $(TargetFrameworkVersion) == 'v1.2' Or $(TargetFrameworkVersion) == 'v1.3' Or $(TargetFrameworkVersion) == 'v1.4' Or $(TargetFrameworkVersion) == 'v1.5')) Or ($(TargetFrameworkIdentifier) == '.NETFramework' And ($(TargetFrameworkVersion) == 'v4.0' Or $(TargetFrameworkVersion) == 'v4.5' Or $(TargetFrameworkVersion) == 'v4.5.1' Or $(TargetFrameworkVersion) == 'v4.5.2' Or $(TargetFrameworkVersion) == 'v4.5.3' Or $(TargetFrameworkVersion) == 'v4.6' Or $(TargetFrameworkVersion) == 'v4.6.1' Or $(TargetFrameworkVersion) == 'v4.6.2'))"> | ||
<PropertyGroup> | ||
<__paket__LibGit2Sharp_props>net40\LibGit2Sharp</__paket__LibGit2Sharp_props> | ||
</PropertyGroup> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Paket noise again. PLease revert all the file...
@@ -183,6 +183,22 @@ | |||
<None Include="paket.references" /> | |||
</ItemGroup> | |||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> | |||
<Choose> | |||
<When Condition="$(TargetFrameworkIdentifier) == '.NETFramework' And ($(TargetFrameworkVersion) == 'v4.0' Or $(TargetFrameworkVersion) == 'v4.5' Or $(TargetFrameworkVersion) == 'v4.5.1' Or $(TargetFrameworkVersion) == 'v4.5.2' Or $(TargetFrameworkVersion) == 'v4.5.3' Or $(TargetFrameworkVersion) == 'v4.6' Or $(TargetFrameworkVersion) == 'v4.6.1' Or $(TargetFrameworkVersion) == 'v4.6.2')"> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Paket noise again. Please revert the file...
//Ensure our Branch was migrated... | ||
Assert.NotNull(branch); | ||
|
||
// So, it turns out GetRootChangesetForBranch is really the unit under test here. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We know that there a lot of things that could be improved in our tests.
We are fine with these type of integration tests because the cases that we want to tests are difficult to build with pure unit tests :(
You could keep the test like that.
Do you have problem updating you pull request. |
Yes, because I was working on this as part of a project at work and I’ll be moving on within the week ☺ From: Philippe Miossec [mailto:notifications@github.com] Do you have problem updating you pull request. — |
@pmiossec I wouldn't mind putting this into a state suitable for merging. This will help a great many people with using git-tfs. If @jeremy-sylvis-tmg is unwilling to fix this up, I'll take a look into doing it. |
@jeremy-sylvis-tmg 😢 |
@pmiossec: Something came up last week and I didn't get to this. I hope to get to it sometime this week, though. Just wanted to ping you and let you know I didn't forget!! |
No problem since you are still on it ;-). I understand that it is not
always easy to find some time to contribute.
|
Sorry, things have been hectic. I started on this tonight. Hopefully I can finish this this weekend. I can't wait to see this merged. BTW, do you know, is there a way to get this pull request directly into my clone of the git-tfs project? Optimally, I would love to pull this pull request into a feature branch off of If this isn't easy to do, I'll probably end up creating a new pull request with the updated changes contained in this pull request. |
@fourpastmidnight This might work....
Unfortunately, there isn't a great way to have multiple collaborators work on a single PR. You can do it by adding each other as collaborators to your individual forks (https://github.com/fourpastmidnight/git-tfs/settings/collaboration), I think. |
Thanks @spraints. |
@fourpastmidnight Thanks. Good work and good luck ;) |
@jeremy-sylvis-tmg is the original author of this commit. He originally issued Pull Request git-tfs#973. However, a code review was performed by myself and @pmiossec whereby changes were requested. Unfortunately, the author of the pull request declined to make the requested changes due to time constraints. Because the changes implemented in this commit could potentially solve a long outstanding problem in how git-tfs currently detects branch point changeset detection, I have recreated this commit with the requested changes. Basically, this commit allows gits-tfs to properly clone a TFS branch into a git repository when the branch was first created as a folder, deleted, and subsequently created as an actual TFS branch: *--C1--C2--C3--C4(X)--*--*--* \ C5(?)--*--* In the diagram above, a folder would be created at C3 called 'Branch'. At C4, it was determined that either C3 was a mistake, or simply that a true TFS branch was desired as opposed to a TFS folder. So at C4, the folder named 'Branch' is deleted. At C5, an actual TFS branch called 'Branch' is created, and C5 is the first changeset on TFS branch 'Branch'. Prior to this commit, Git-Tfs would get "confused" because branches and folder in TFS are similar, but not the same--and there's no analogue in Git whatsoever. The branch 'Branch' usually fails to clone properly, and IIRC, you'll get messages such as "Could not find parent changeset for branch 'Branch'". In my experience, providing a parent changeset ID does not always resolve the situation satisfactorily. The changes in this commit detect this situation. At C3, it detects that a folder was created, called 'Branch'. TFS folders are not branches, and so this commit causes git-tfs to keep searching through TFS history for the most recent branch point. So, when the folder named 'Branch' is deleted at C4, git-tfs will continue to search for merge history, which it finds at C5, where the TFS branch named 'Branch' is created. This is a true branch point off of the main line. Because C3 and C4 effectively "cancel" each other out, the resulting Git history after cloning this TFS repository history looks like the following (NOTE: this author is unsure how git-tfs represents commits C3 and C4 in the commit history of a Git repository since Git has no concept of "folders"): *--C1--C2--C3--C4(X)--*--* \ C5--*--* NOTE: This commit does add some methods to an interface. As such, the next version of Git-TFS should have it's minor version incremented; e.g. the next version of Git-Tfs released containing this commit should be in the 0.26.x series. Signed-off-by: Craig E. Shea <craig.e.shea@gmail.com>
@spraints, @pmiossec I have just pushed up a branch to my clone of this project containing the core changes of this PR with the requested changes. Is it possible for me to "force push" to this pull request instead of creating a new one? If not, I'll just create a new PR referencing this PR as the original source of the changes. Let me know how you wish me to proceed. |
Do the easier. I think that's doing a new PR...
|
@pmiossec Great, thanks! I'll be submitting the PR momentarily. |
@jeremy-sylvis-tmg is the original author of this commit. He originally issued Pull Request git-tfs#973. However, a code review was performed by myself and @pmiossec whereby changes were requested. Unfortunately, the author of the pull request declined to make the requested changes due to time constraints. Because the changes implemented in this commit could potentially solve a long outstanding problem in how git-tfs currently detects branch point changeset detection, I have recreated this commit with the requested changes. Basically, this commit allows gits-tfs to properly clone a TFS branch into a git repository when the branch was first created as a folder, deleted, and subsequently created as an actual TFS branch: *--C1--C2--C3--C4(X)--*--*--* \ C5(?)--*--* In the diagram above, a folder would be created at C3 called 'Branch'. At C4, it was determined that either C3 was a mistake, or simply that a true TFS branch was desired as opposed to a TFS folder. So at C4, the folder named 'Branch' is deleted. At C5, an actual TFS branch called 'Branch' is created, and C5 is the first changeset on TFS branch 'Branch'. Prior to this commit, Git-Tfs would get "confused" because branches and folder in TFS are similar, but not the same--and there's no analogue in Git whatsoever. The branch 'Branch' usually fails to clone properly, and IIRC, you'll get messages such as "Could not find parent changeset for branch 'Branch'". In my experience, providing a parent changeset ID does not always resolve the situation satisfactorily. The changes in this commit detect this situation. At C3, it detects that a folder was created, called 'Branch'. TFS folders are not branches, and so this commit causes git-tfs to keep searching through TFS history for the most recent branch point. So, when the folder named 'Branch' is deleted at C4, git-tfs will continue to search for merge history, which it finds at C5, where the TFS branch named 'Branch' is created. This is a true branch point off of the main line. Because C3 and C4 effectively "cancel" each other out, the resulting Git history after cloning this TFS repository history looks like the following (NOTE: this author is unsure how git-tfs represents commits C3 and C4 in the commit history of a Git repository since Git has no concept of "folders"): *--C1--C2--C3--C4(X)--*--* \ C5--*--* NOTE: This commit does add some methods to an interface. As such, the next version of Git-TFS should have it's minor version incremented; e.g. the next version of Git-Tfs released containing this commit should be in the 0.26.x series. Signed-off-by: Craig E. Shea <craig.e.shea@gmail.com>
I ran into an issue nearly identical to #955 - someone earlier in a project's history created a "branch" folder, deleted the folder, and then properly created the new branch by branching off our root branch.
As a result, git-tfs was unable to determine the root changeset because it assumed the first changeset in the child branch was always the actual branch point.
Assume we have this:
$/MyProject/Trunk - C100
We now create $/MyProject/Branch as a folder - C101.$/MyProject/Branch to $ /MyProject/ChildBranch (still at C105 from its parent) -> C108.
We do some more work on Trunk - C102-105.
We realize the error of our ways and delete the $/MyProject/Branch folder - C106.
We recreate $/MyProject/Branch by branching Trunk C105 -> C107.
We further branch
We do some work on $/MyProject/Branch - C109-C115.
We merge that work to $/MyProject/ChildBranch - C116.
During the clone, $/MyProject/Trunk would fetch correctly.$/MyProject/ChildBranch correctly but can't find changesets corresponding to the merge of C109-C115 into it, because git-tfs only read pre-branch history of $ /MyProject/Branch.
Git-tfs would fail to determine the root changeset for $/MyProject/Branch. Even if I specify a changeset, it gets confused because it only reads from the folder creation up through the deletion - C106 and C107.
Git-tfs would detect
The changes in this pull request fix these scenarios by:
One unit test was added to illustrate this problem but the test itself is limited as most of the affected code is faked for tests. It does, at least, serve as an illustration of the problem.