My source and target files are different, but merge tells me there are no changes to merge

When TFS does a merge, it bases the merge on prior merge history, not on the actual contents of the source and target files. There are many reasons why this is necessary, some of which will become apparent by reading this post. For example, a merge may result in a conflict (changes made to both the source and target files). In resolving the conflict you have many choices, including “Keep target version” (sometimes called “Accept Yours”) or “Take Source version” (sometimes called “Accept Theirs”). Sometimes in resolving a merge conflict, you take some changes from the source file and some from the target file. Depending on how you resolve a merge conflict, the source and target files could end up being very different. A subsequent merge will show “No changes to merge” even though content of the source and target files is different.

Is it possible that there was, at one time, a merge with the discard option performed (using the command line TF merge /discard).

When you use the discard switch, TFS will consider unmerged changeset(s) (changesets in the source branch that are not in the target branch) to now be merged, but it will not actually change the content in the target branch’s file.

Another possibility is that a merge conflict occurred on a prior merge, and the user selected “Keep target version” on the merge conflict resolution dialog. This will also update the history to indicate that the changeset was merged from source to target, but the actual change in the source file was not applied to the target file.

If there is a changeset that was previously merged (perhaps incorrectly) and you want to merge it again (for example, I want to merge changeset #123456 from $/Source/File.cs to $/Target/File.cs again), use the /force option with the tf merge command. The /force flag ignores merge history that indicates a particular changeset was previously merged from source to target (perhaps incorrectly), and merges the changeset again. You can do a /force merge for a single changeset or for a range of changesets. For just changeset #123456 the command would be: “tf merge /force $/Source/File.cs;C123456~123456 $/Target/file.cs”

There are some other diagnostic things you might do:

The Command Line TF Merges (note the plural), will show you the changesets from the source file that were previously merged to the target file (and the resulting changeset in the target file)

The syntax would be: “tf merges $/Source/File.cs $/Target/File.cs”

There is more information on the tf merges command here: https://msdn.microsoft.com/en-us/library/656cs2x5.aspx

The /candidate option on a merge will show you the changesets in the source file that are candidates to be merged to the target file:

The syntax would be: “tf merge /candidate $/Source/file.cs $/Target/file.cs”

There is more information on the options for tf merge here: https://msdn.microsoft.com/en-us/library/bd6dxhfy.aspx

You might also run tf history, which displays the revision history for one or more files, folders or both. There is more information on the tf history command here: https://msdn.microsoft.com/en-us/library/yxtbh4yh(v=VS.100).aspx