TFS on VSTS: `tf vc unshelve <shelvesetname>` fails silently not downloading changes - tfs

Preparing new build definition working with TFS version control on VSTS I encountered strange beahaviour:
When doing a build from shelveset in log files I can see that sources from main repo are downloaded (and they are indeed) and later in logs there is information about unshelving changes from shelveset - but those files are not actually downloaded, what causes later pipeline tasks to fail.
Example logs:
2018-09-26T09:47:29.6580577Z ##[command]tf vc workspace /delete ws_5_23;1c4749a7-aba9-45f6-93c1-0b3c777d3de3 /collection:<collectionname>/ /loginType:OAuth /login:.,*** /noprompt
2018-09-26T09:47:32.1224786Z ##[command]tf vc workspace /new /location:local /permission:Public ws_5_23 /collection:<collectionname>/ /loginType:OAuth /login:.,*** /noprompt
2018-09-26T09:47:33.8329522Z ##[command]tf vc workfold /unmap /workspace:ws_5_23 $/ /collection:<collectionname>/ /loginType:OAuth /login:.,*** /noprompt
2018-09-26T09:47:35.4446518Z ##[command]tf vc workfold /map /workspace:ws_5_23 $/<path> <path2> /collection:<collectionname>/ /loginType:OAuth /login:.,*** /noprompt
2018-09-26T09:47:36.9498633Z ##[command]tf vc workfold /map /workspace:ws_5_23 $/<path3> <path4> /collection:<collectionname>/ /loginType:OAuth /login:.,*** /noprompt
2018-09-26T09:47:38.6423920Z ##[command]tf vc get /version:50687 /recursive /overwrite C:\agent\_work\5\s /loginType:OAuth /login:.,*** /noprompt
2018-09-26T09:47:41.5812148Z C:\agent\_work\5\s\Main\Source:
2018-09-26T09:47:41.5826483Z Getting BI
Later there are a lot of files that are downloaded - and they are actually downloaded, present on disk.
However, after this:
2018-09-26T09:47:46.3299164Z ##[command]tf vc unshelve <shelvesetname>;<user> /loginType:OAuth /login:.,*** /noprompt
2018-09-26T09:47:48.5345961Z <path4>:
2018-09-26T09:47:48.5346886Z Unshelving edit: <solutionname>.sln
... and a lot of other changes from shelveset
Files that are specified to have been unshelved actually are not - they are not on disk. And pipeline fails later as it cannot find those files.
Few notes :
unshelving those changes locally in Visual Studio 2017 proceeds as expected - files are downloaded to disk.
changes are in two different parent folders each of which is mapped separately in build setting
no error is thrown, it smoothly passes to another pipeline step
How to make TFS actually download those changes from shelveset? Or is it just a TFS bug?

Related

TFS: Overwrite (ALL) local file or folder

I'm trying to get latest on Visual Studio 2017/Angular project on a another machine and hence getting latest all files. It is taking a long time to 'Overwrite local file or folder' individually. Isn't there a way to Overwrite All local files or folders with single click?
In Visual Studio, from the Source Control Explorer, open the folder you want to overwrite. Use Advanced..., Get Specific Version...
And check the option "Overwrite writable files..."
Optionally check "Overwrite all files", but that should not be required and can take up more time.
You can also do this from the commandline:
tf vc get $/project/path /recursive /overwrite /version:T
And optionally to overwrite all files even if your system thinks they are unchanged:
tf vc get $/project/path /recursive /overwrite /force /version:T
Alternatively, you can use undo pending changes to revert to the last checked-in version, or scorch to clear files that aren't even checked in:
tf vc undo /recursive $/Project/path
and
tf vc scorch /recursive $/project/path

How to know the current changeset id TFS Visual Studio

I have this workspace on this machine that is not updated for some days. I want to know the latest changeset Id that exists on this machine.
Let's say the latest changeset that is checked-in is 8400. I want to somehow find the current changeset id of the workspace on this machine, that might be say for example 8329.
Yeah, the tf history command can achieve that.
For your convenience, you can simply copy below strings and save as a cmd/bat file, then run it directly to get the latest changeset ID under the specific directory within the local workspace. (In your scenario you need to enter the root path of your workspace)
ECHO OFF
SET "VSDir=C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\Common7\IDE\CommonExtensions\Microsoft\TeamFoundation\Team Explorer" :: For VS 2017
:: For VS 2015: SET "VSDir=C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE"
CD %VSDir%
SET /p LocalPath=Enter LocalPath:
ECHO.
tf history %LocalPath% /r /noprompt /stopafter:1 /version:W
ECHO.
PAUSE
Besides, you can also use the Version Control client API to achieve that.
For more information please refer to: How to determine the latest changeset in your workspace
You may use tf history command. Go to root workspace folder and:
tf history . /recursive /noprompt /stopafter:1 /version:W

Copy source files to other TFS

We have a TeamCity/Octopus setup that runs great for several projects.
A new client wants access to the source code during development. Is it possible to copy code from our TFS to an other TFS using TeamCity? It does not need to be real-time. Daily copies are OK.
Not sure if we should use TeamCity for this or if there are possibilities within TFS itself.
You could setup a daily build schedule and use the TFS command line utilities to transfer the files to another server. You'll probably get all kinds of sync issues along the way, unless you always take your own solution as the current situation.
Look at tf.exe, especially the workspace, workfold commands and add, delete, and optionally destroy. Complete the job with a tf checkin.
Process as follows:
Create a workspace on your source TFS server (or use the built-in workspace features in team city): tf workspace /new
Map the folders you want to share: tf workfold /map
Get the files to the machine that's doing the transfer: tf get /recursive
Create a workspace on your target TFS server: tf workspace /new
Map the folders you want to share to tf workfold /map to a new folder that's not mapped to the source TFS server.
WS2 delete the files in the target folder: tf delete * /recursive
WS2 Check in to make sure you won't get any conflict remotely: tf checkin /recursive
WS1 -> WS2 Copy the files from the first workspace to the second: xcopy
WS2 Add all files: tf add * /recursive
WS2 Checkin all files tf checkin * /recursive
WS2 & WS2 Delete the workspace: tf workspace /delete
(Optional) Delete the files in the folders of the deleted workspaces on disk.
PS: if you move to git, this all becomes a lot easier, since the distributed nature of git is kind of meant for scenarios like these.

how to map the TFS workspace to local by using Command Line Client

I am trying to map the TFS workspace to local by using the below comment
tf workfold /map /login:username,pwd /server:http://servername:8080/tfs /workspace:'$/source/app/TFS_Label' 'C:\TFS_Label'
but am getting the error saying
An argument error occurred: workfold requires zero, one, or two path arguments.
kindly help on this issue.I am new to TFS.
You're not quite passing in the correct arguments to TF Workfold Also the server parameter is deprecated.
If you're using TFS 2005 / 2008 then you need to use server, if your using TFS 2010 or above then you need to use collection instead. Having said that server will work if you have a single collection in TFS that is called "DefaultCollection" on newer versions of TFS
The syntax is
tf workfold /map serverfolder localfolder
[/collection:TeamProjectCollectionUrl]
[/workspace:workspacename]
[/login:username,[password]]
So for TFS 2010 or newer your command should look something like this
tf workfold "$/source/app/TFS_Label" "C:\TFS_Label" /map /login:username,pwd /collection:http://servername:8080/tfs/defaultcollection /workspace:"MyWorkspaceName"
For older versions of TFS use
tf workfold "$/source/app/TFS_Label" "C:\TFS_Label" /map /login:username,pwd /server:http://servername:8080/tfs /workspace:"MyWorkspaceName"
A workspace is the container for the folder mapping so if you have an existing workspace then you can use that. If not then you can create a workspace using the TF Workspace /new

Convert changeset(s) to shelveset

Is it possible to create a shelveset from the diff of two versions of one branch just by some operations in tfs/tfpt?
e.g. create a shelveset from (changeset 2013 -> changeset 2034)
It is possible to create a shelveset from a changeset with some limitations. I needed to rollback a change from a branch to remove it from a release but it wasn't in any other branch either so I wanted to keep the change in a shelveset. I achieved this as below:
Rollback the changeset and check in the rollback.
Rollback the rollback changeset. This gives me a set of pending changes containing the original change.
Shelve the pending changes.
You could apply this technique to the case described in the question but it would be a lot of manual effort as it would have to be repeated for every changeset. It would also generate a lot of mess in TFS as you would have to check in the rollbacks of the rollbacks too.
No, it's not possible. Changesets and shelvesets are different things, with different purposes. You could probably write a plugin to do what you're after (retrieve changeset, check out the files, shelve the files).
It's not impossible. Technically speaking you can do it, although you may not want to. I'll let the reader decide.
You may want to do this in a new workspace.
Get the Changeset in question (new code)
Move all the source to temp folder. (don't move the $tf folder). Source tree should now be empty.
Get the previous Changeset.
Mirror copy the new code on top of the old
Do a Reconcile.
Now you can create the Shelveset.
If you are able to focus to a particular folder, then it will go faster, and you can automate it. Here's example command lines that will do this. I just tried it and it worked for me.
In this example, I point to a folder from the root called "Src". Change it your root folder.
md tmpws
cd tmpws
tf vc workspace /new /noprompt tmpws /location:local /permission:private
tf vc get "$/Src" /version:C2222 /recursive /noprompt
cd ..
md tmp
move "tmpws\Src" tmp
cd tmpws
tf vc get "$/Src" /version:C1111 /recursive /noprompt /force /overwrite
cd ..
robocopy "tmp\Src" "tmpws\Src" /mir
tf vc reconcile /promote /adds /deletes /diff /recursive /noprompt
tf vc shelve /replace /noprompt mychange
tf vc undo "$/Src" /recursive /noprompt
tf vc workspace /delete tmpws
cd ..
rmdir /q /s tmp
rmdir /q /s tmpws
While this solution doesn't involve a pure TFS solution, it doesn't involve mucking with the TFS changeset history like Lee Richardson's answer does.
You can use Git-TFS to clone a TFS repository or branch, then create a new branch from a previous commit (TFS check-in), reapply changes from a newer commit and post that as a shelveset:
Look in the git log for the commit before the one you want to create a changeset for:
$ git log --oneline
AAAAAAA Newest commit
BBBBBBB The commit for which I want a shelveset
CCCCCCC The commit where I will create a new branch from
Create a new branch from the commit that occurs before the one you want to retroactively create the shelveset for:
$ git checkout -b CCCCCCC
Checkout the changes from the commit for which you want to create the shelveset for:
$ git checkout BBBBBBB -- .
Commit these staged files:
$ git commit -m "Committing stuff for a retroactive shelveset that does X, Y and Z."
Create the shelveset:
$ git tfs shelve my_retroactive_shelveset HEAD
Advantages
This keeps the TFS changeset history clean without requiring you to revert a changeset, create a shelveset to un-revert the previously reverted changeset.
Since the shelveset was created from a branch in Git, you can delete that branch and still keep your Git-TFS history clean as well.
Disadvantages
It's not a pure TFS solution
Each commit will create a shelveset. So we can find a shelveset created while the commit was initiated. That will have exact same changes. We dont need to create new shelveset.

Resources