Perforce, how can I determine changelist of last sync - perforce

How can I determine the changelist my workarea was last synced to, regardless of which options were used by tha last 'p4 sync' (-f, -k, etc....).
I don't think its 'p4 changes -m 1 #have' (that's the revision of the client, correct ?). I observed what 'p4 changes -m 1 #have was, did a sync (got some updated files), observed again and it didn't change. And I can't see any others in 'p4 help revisions' that look like this.
I don't think topic "Determining the last changelist synced to in Perforce" answers this question as it seems to solve a problem for an automatic build system (which is not what I'm doing).
Thanks in Advance for any help !

p4 changes -m1 #have should get you something similar to the right answer. Note that what that will tell you exactly is: "among all of the revisions in my workspace, and all of the associated changelist numbers, which is the highest one?" So if you synced ONE file from the latest changelist, but a bunch of other files are unsynced, you'll get the latest change even though you're not synced to it. You'll also miss changelists that consist solely of deleted files (since you don't #have those).
The p4 cstat command will give you more thorough information on a per-change basis, telling you for each change whether you've synced all, some, or none of it.

Related

Determine when perforce changelist was last updated

Does perforce track the time and date at which changes were made to changelists? For example, updating the description text, or shelving different revisions of files into the changelist? And if so, can this information be accessed using p4 command line?
p4 changes -t will include information about the creation time of the changelist, but not the update. p4 describe doesn't seem to include any flags related to time. p4 fstat can show time information about the files in a changelist, but not the changelist itself.
No, changelists are not versioned objects (not even in the spec depot, annoyingly). The only ways to track changes to changelists are to go under the covers, e.g.:
Scrape information from the journal file (this requires some understanding of Perforce's db schema)
Add triggers on each command that might update a changelist in the ways you want to track (this requires exhaustive understanding of Perforce's command API so you don't "miss" anything that you need to trigger on).

Reverting multiple checkins in perforce

I have made several checkins using perforce. I have no realized that all of them are unnecessary. I would like to revert all the changes for the last x revisions in the working directory, update the version number, and check in.
I am familiar with Mercurial. The way that I would it for that would be:
$ hg revert -r last_good_changeset .
$ edit version-number.txt
$ hg ci
Is there a way to do something similar in perforce?
In Perforce, a revert refers to restoring a file to the state it was in before it was checked out. What you're looking to do is back out a submitted changelist. This Perforce KB article has a few methods to do what you're trying to do, depending on your particular circumstance.
For example, if you have revisions #1 - #6 of a particular file, and you want to roll back to revision #3, you'd do this:
p4 sync myfilename#3
p4 edit myfilename
p4 sync myfilename
You're telling Perforce to get revision #3 from the depot, check it out for edit, then try to sync it back up to #head (the latest version in the depot). Since the file is checked out from an earlier revision, Perforce schedules a resolve so you need to tell it what you want to do with the file: accept the version in the depot, accept your local changes, or try to merge the two. You'll want to tell Perforce to accept the local version (or in Perforce parlance "yours"):
p4 resolve -ay myfilename
Now that it's resolved, you can submit it with:
p4 submit
If you have a series of files you want to do this with (for example, you've edited a bunch of files in a given directory and have checked them all in together several times, and you want to back out all of those), you can use changelist syntax as well. For example, if you want to roll everything back in a given directory to changelist 123, you can do this:
p4 sync //depot/some/path/*#123
p4 edit //depot/some/path/*
p4 sync //depot/some/path/*
p4 resolve -ay //depot/some/path/*
p4 submit
This will work for any revision modifier (see p4 help revisions for alternate methods of specifying the version you want).
The rollback function is specifically designed to do this. It goes back to a certain date/time or change list # and reverts all changes in the window you give it.
Simply right click on the file in question (P4V obviously) and select rollback. It will bring up this box. Not sure how to execute from command line...Ill see if I can figure it out and add that info.

How to revert to an earlier revision of a project in Perforce following a deletion?

Let's say I have a project under //depot/MyProject. At changelist 1001, this project took a major change in direction, changing everything about it. At changelist 2001, it got p4 deleted. The depot is now at change 3000.
I'd like to restore //depot/MyProject back to its state at changelist 1000. Specifically, I'd like the revision history to record the fact that change 3001 is an integration of change 1000 - i.e. the last version of this project before the major change.
Can Perforce do this at all? Or do I have to rename it into something like //depot/MyProjectOriginal, because //depot/MyProject is now tainted with all those deleted revisions?
(the naive attempt to p4 integrate //depot/MyProject/...#1000 //depot/MyProject/... fails with an "all revision(s) already integrated" message)
You cannot force the integration.
You have two options: you can create a branch using changelist 1000 as the base; or sync to changelist 1000, check out all files, and then submit (a.k.a rolling back).
Option 1
If you do want the history of your changes between 1001-3000 (i.e. a fresh start from changelist 1000) then this is the better option. Using P4V, create a new branchspec and then perform an integrate from your current project to the new branch at changelist 1000. This will be submitted as changelist 3001, when you compare differences between revisions, you will not see of the changes between 1001-3000.
In the P4 visualizer this will appear as a new branch creation at 1000.
Option 2
Sync to changelist 1000, check out all files, and then submit. There should not be any conflicts to resolve. This will be submitted as changelist 3001, however when you review history you will see the everything.
I hope this makes sense, any questions, please ask.
I don't believe that you can integrate files on top of one another like that. I think that you have two options.
If you are willing to move the files, you can do a
p4 integ //depot/MyProject/...#1000 //depot/MyOriginal/Project/...
and that will integrate MyProject at changelist 1000 to the new location.
If you'd like to keep the project at the same place, you can do that as well. It's really easiest in p4v - you can right click on the folder in workspace or depot view and choose "rollback...". In the subsequent dialog, you can then pick a changelist (or date, revision, etc) to roll the folder back to. In your case, I think that you would choose changelist 1000. Stick the files into a new pending changelist (I think that this is always good practice). You can then run a preveiw (to see what would happen), save the contents to a new changelist (so that you can inspect file contents before submitting), or just go for broke and pull the trigger and submit (I generally wouldn't recommend this).
HTH
Just do:
p4 copy //depot/MyProject/...#1000 //depot/MyProject/...
This also make a nice revision graph.
Though there is an accepted answer and plenty of other solutions, none of them works for me coz I need to rollback a large directory (with GBs of data)
Here is the way I used, which works fine for huge directory:
(Suggested to do in a new and clean workspace, though not strictly required)
Assuming the directory to rollback is //depot/foo/bar and you want to rollback to changelist 1234
Make sure no one is locking any files, and make sure the directory you are trying to rollback exists in your client spec
p4 copy -v //depot/foo/bar/...#1234 //depot/foo/bar/...
p4 submit
p4 copy -v is the meat of the solution. It tells Perforce server to perform virtual copy, which means Perforce copies the files but not actually in your workspace. This avoid huge data transfer for file content (when copying and when submitting). In my case, by using "rollback" in P4V (which is doing non-virtual copy), it took over an hour just for copy, and over an hour for submit for my folder. With virtual copy, whole process took me around 1 minute.
The most important thing is, it keep a sensible history. You can see your files being updated and rolled back, and all previous history exists.
use
p4 integrate -f //depot/MyProject/...#1000 //depot/MyProject/...
The -f flag means force an integration even if they have already been integrated.
From http://www.perforce.com/perforce/doc.current/manuals/cmdref/integrate.html

Determining the origins of a Perforce file with the `move/add` action.

I'm working on a script that processes the contents of a Perforce changelist. Each file in the changelist will be handled differently depending on the action associated with it.
I've already tackled the actions edit, add, integrate, and delete. So far, so good. However, for move/add and move/delete, I need a reliable means of determining the file's origin and destination, respectively. I've looked through the documentation for p4 fstat and haven't turned up anything of use.
Any ideas? Thanks.
Look at p4 filelog . It will give you the history of the moves. The -ztag output might or might not be useful for your purposes.

Determining the last changelist synced to in Perforce

A question that occasionally arises is what is the best way to determine the changelist that you last synced to in Perforce. This is often needed for things like injecting the changelist number into the revision info by the automatic build system.
I recommend the opposite for automatic build systems: you should first get the latest changelist from the server using:
p4 changes -s submitted -m1
then sync to that change and record it in the revision info. The reason is as follows. Although Perforce recommends the following to determine the changelist to which the workspace is synced:
p4 changes -m1 #clientname
they note a few gotchas:
This only works if you have not submitted anything from the workspace in question.
It is also possible that a client workspace is not synced to any specific changelist.
and there's an additional gotcha they don't mention:
If the highest changelist to which the sync occured strictly deleted files from the workspace, the next-highest changelist will be reported (unless it, too, strictly deleted files).
If you must sync first and record later, Perforce recommends running the following command to determine if you've been bit by the above gotchas; it should indicate nothing was synced or removed:
p4 sync -n #changelist_number
Note that this method doesn't work if a file is added in a changelist (n-1) and then deleted in the very next changelist (n). p4 changes -m1 #clientname and p4 changes ...#have both return n-3 and p4 sync -n #n-3 will say "file(s) up-to-date."
Just to answer this myself in keeping with Jeff's suggestion of using Stackoverflow as a place to keep technical snippets....
From the command line use:
p4 changes -m1 #<clientname>
And just replace with the name of your client spec. This will produce output of the form:
Change 12345 on 2008/08/21 by joebloggs#mainline-client '....top line of description...'
Which is easily parsed to extract the changelist number.
You may try finding the maximum change number in the output of the "p4 files" command. The working directory should not contain post-sync commits, though. This is just a tad better than
p4 changes -m1 "./...#have"
as the latter seems to run on the server and may fail on big source trees due to "MaxResults" limits.
$ p4 changes -m1 "./...#have"
Request too large (over 850000); see 'p4 help maxresults'.
$ p4 -G files "./...#have" | python c:/cygwin/usr/local/bin/p4lastchange.py
Files: 266948
2427657
where p4lastchange.py is based on the code from the Using P4G.py From the Command Line presentation by J.T.Goldstone, Kodak Information Network/Ofoto, April 15, 2005.
#! /usr/bin/env python
import sys, os, marshal
if os.name == "nt":
# Disable newline translation in Windows. Other operating systems do not
# translate file contents.
import msvcrt
msvcrt.setmode( sys.stdin.fileno(), os.O_BINARY )
lastcl = 0
num = 0
try:
while 1:
dict = marshal.load(sys.stdin)
num = num + 1
for key in dict.keys():
# print "%s: %s" % (key,dict[key])
if key == "change":
cl = int(dict[key])
if cl > lastcl:
lastcl = cl
except EOFError:
pass
print "Files: %s" % num
print lastcl
p4 changes -m1 #clientname which is the "recommended" way to do it for my client takes about 10 minutes
this is what I use:
p4 cstat ...#have | grep change | awk '$3 > x { x = $3 };END { print x }'
for the same client takes 2.1 seconds
If you are using P4V you can do this graphically:
In the Dashboard tab (View->Dashboard) choose a folder and you will see a list of changelists that the folder isn't yet updated with. Note the lowest number (in the highest row).
Make sure that in the Workspace Tree you have selected the same folder as previously in the Dashboard. Then go to the History tab (View->History) and scroll down to the number noted previously. The number just below that number is the number of your current changelist.
You could also use the cstat command:
p4 help cstat
cstat -- Dump change/sync status for current client
p4 cstat [files...]
Lists changes that are needed, had or partially synced in the current
client. The output is returned in tagged format, similar to the fstat
command.
The fields that cstat displays are:
change changelist number
status 'have', 'need' or 'partial'
For a serious build (one that is being prepared for testing), explicitly specify the desired label or changelist number, sync to label, and imbed it in build artifacts.
If a changelist (or label) is not given, use p4 counter change to get the current change number, and record it. But you still need to sync everything using that change number.
I don't think you can achieve exactly what you want, because in general, an entire workspace isn't synced to a particular changelist number. One can explicitly sync some files to older revisions, and then a single changelist number is meaningless. That's why a fresh sync is required to ensure that a single changelist number accurately represents the code version.
Regarding the comments: Yes, my answer is intended for use by configuration managers preparing a build to give to QA. Our developers don't normally sync as part of a build; they do a build prior to submitting—so that they can make sure their changes don't break the build or tests. In that context, we don't bother to embed a repository label.
With your approach, you are making the assumption that your whole workspace was synced to head at the time of your last changelist submission, and that changelist included all of your open files. It's too easy to be mistaken in those assumptions, hard to detect, and horribly expensive in terms of lost time. On the other hand, solving the problem is easy, with no drawbacks. And because a changelist number can be explicitly specified, it doesn't matter what revision you need or how quickly the codebase is changing.
For the whole depot (not just your workspace/client)
p4 counter change
does the job, just telling the last changelist.
The best I've found so far is to do your sync to whatever changelist you want to build and then use changes -m1 //...#have to get the current local changelist (revision).
p4 sync #CHANGELIST_NUM
p4 changes -m1 //...#have | awk '{print $2}'
Gives you the changelist number that you can the use wherever you want. I am currently looking for a simpler way than p4 changes -m1 //...#have.
I am not sure if you got the answer you needed but I had a similar problem. The goal was to write in our logger the specific version of the project. The problem was that while we are making our own makefile, the overall build system is controlled by our configuration management. This means that all the solutions which say "sync to something then do something" don't really work and I didn't want to manually change the version whenever we commit (a sure source for errors).
The solution (which is actually hinted in some of the answers above) is this:
in our makefile, I do p4 changes -m1 "./...#have"
The result for this is Change change_number on date by user#client 'msg'
I simply create the message into a string which is printed by the logger (the change number is the important element but the other is also useful to quickly decide if a certain version contains changes you know you made yourself without going to perforce to check).
Hope this helps.

Resources