Retrieving the current change list number of a Perforce Workspace including reverts - perforce

The command p4 changes -m1 //path/to/your/project/...#have to get the current changelist, as shown by this solution, works great until we have a commit that reverts the commit immediately before it.
For example, if I have the following setup:
4 - CL#3 was reverted and submitted here
3 - Somebody submitted this CL
2 - <= Current workspace is here
1
0
I run p4 changes -m1 //path/to/your/project/...#have, I get 2 as expected
I then sync to 4 and run the command again, but I still get 2. I assume this is because there is no new file locally and perforce still thinks I am on 2 when I should be on 4.
This is an issue because it breaks some scripts that run on new CLs that are coming in. Is it possible to either ignore such CLs or adjust the command in some way to know that are on 4 even though there are no file changes (because 4 is a revert of 3)?

Reproducing your setup by adding a file in change 3 and then deleting it in change 4, we can indeed see that changes -m1 #have returns change 2:
Sams-MacBook-Pro:test samwise$ p4 changes
Change 4 on 2023/01/26 by samwise#samwise-dvcs-1517552832 'delete ola'
Change 3 on 2023/01/26 by samwise#samwise-dvcs-1517552832 'add ola'
Change 2 on 2023/01/26 by samwise#samwise-dvcs-1517552832 'add bar'
Change 1 on 2023/01/26 by samwise#samwise-dvcs-1517552832 'add foo'
Sams-MacBook-Pro:test samwise$ p4 sync #4
#4 - file(s) up-to-date.
Sams-MacBook-Pro:test samwise$ p4 changes -m1 "#have"
Change 2 on 2023/01/26 by samwise#samwise-dvcs-1517552832 'add bar'
This is because changes -m1 #have is just returning the maximum change among those returned by p4 files #have:
Sams-MacBook-Pro:test samwise$ p4 files "#have"
//stream/main/test/bar#1 - add change 2 (text)
//stream/main/test/foo#1 - add change 1 (text)
We do not have any file belonging to change 4, because change 4 consists solely of deleted revisions, which by definition are never synced to the workspace.
Sams-MacBook-Pro:test samwise$ p4 files #=4
//stream/main/test/ola#2 - delete change 4 (text)
When we sync to change 4, we don't get ola#2, we get ola#none, exactly as if we'd synced to change 2 (or any change where ola does not exist as a non-deleted file):
Sams-MacBook-Pro:test samwise$ p4 sync #4
#4 - file(s) up-to-date.
Sams-MacBook-Pro:test samwise$ p4 sync #2
#2 - file(s) up-to-date.
Sams-MacBook-Pro:test samwise$ p4 have ola
ola - file(s) not on client.
At this point it's actually equally correct to say that we're synced to either change 2 or change 4, since either will give us the same set of files. In fact, if we diff the depot at those two changelists, we can see that those two points in time are effectively identical:
Sams-MacBook-Pro:test samwise$ p4 diff2 -q ...#2 ...#4
...#2 - no differing files.
If we want to divine change 4 from our current sync state rather than just the effectively identical change 2, the p4 cstat command is a useful tool -- this will iterate through all the changes for which our workspace contains all revisions up to that point:
Sams-MacBook-Pro:test samwise$ p4 cstat
... change 1
... status have
... change 2
... status have
... change 4
... status have
Since we have all changes up thru 4 according to p4 cstat, that is likely to be the best answer to the question "what change am I synced to?"

Related

p4 interchanges showing integrated changelists

My team is using a bash script that runs p4 interchanges -S $stream in order to determine which task streams still need to be copied up to their parents.
In the case of a stream that has two changelists where one undoes the other (where the cumulative diff is empty), the script is not saying that all revisions are already integrated, despite the stream having already been copied up to its parent.
Is there a way to make p4 interchanges recognize that the empty diffs do not need integration, or is there another p4 command we could be using here?
It depends on how you undid the changelist. If you used the p4 undo command, then p4 integrate (and by extension p4 interchanges) is able to recognize the relationship between those revisions by following the integration records created by p4 undo. If you undid it with a manual edit, then each revision looks like a new edit from the metadata perspective (which is all that integrate/interchanges considers -- actual file content inspection is delegated to resolve).
Here's an example file that (I think) demonstrates the situation you're talking about with an undone change, such that the cumulative effect is no diff:
C:\Perforce\test\undo>p4 filelog -i bar
//stream/test2/undo/bar
... #3 change 250 integrate on 2021/06/25 by Samwise#Samwise-dvcs-1509687817 (text) 'undo'
... ... undid //stream/test2/undo/bar#2
... #2 change 249 edit on 2021/06/25 by Samwise#Samwise-dvcs-1509687817 (text) 'foo'
... ... undone by //stream/test2/undo/bar#3
... #1 change 248 branch on 2021/06/25 by Samwise#Samwise-dvcs-1509687817 (text) 'foo'
... ... branch from //stream/test2/undo/foo#1
//stream/test2/undo/foo
... #1 change 236 add on 2021/01/28 by Samwise#Samwise-dvcs-1509687817 (text) 'add foo'
... ... branch into //stream/test2/undo/bar#1
As you can see, integrate and interchanges report this as nothing to do:
C:\Perforce\test\undo>p4 interchanges bar foo
bar - all revision(s) already integrated.
C:\Perforce\test\undo>p4 integ bar foo
bar - all revision(s) already integrated.
This is thanks to the undo/undone credits that you can see in the filelog. integrate can see that #3 is just the inverse of #2, so it adds them together and finds nothing to do.
Now suppose I add another edit and do a "fake undo" (this is what happens if you e.g. roll back a change with an old script or version of P4V that doesn't know about p4 undo):
C:\Perforce\test\undo>p4 edit bar
//stream/test2/undo/bar#3 - opened for edit
C:\Perforce\test\undo>echo asdfasdf >> bar
C:\Perforce\test\undo>p4 submit -d edit
Submitting change 251.
Locking 1 files ...
edit //stream/test2/undo/bar#4
Change 251 submitted.
C:\Perforce\test\undo>p4 sync bar#3
//stream/test2/undo/bar#3 - updating c:\Perforce\test\undo\bar
C:\Perforce\test\undo>p4 edit bar
//stream/test2/undo/bar#3 - opened for edit
... //stream/test2/undo/bar - must sync/resolve #4 before submitting
C:\Perforce\test\undo>p4 sync bar
//stream/test2/undo/bar#4 - is opened and not being changed
... //stream/test2/undo/bar - must resolve #4 before submitting
C:\Perforce\test\undo>p4 resolve -ay
c:\Perforce\test\undo\bar - vs //stream/test2/undo/bar#4
//Samwise-dvcs-1509687817/undo/bar - ignored //stream/test2/undo/bar
C:\Perforce\test\undo>p4 submit -d "fake undo"
Submitting change 252.
Locking 1 files ...
edit //stream/test2/undo/bar#5
Change 252 submitted.
C:\Perforce\test\undo>p4 integ -n bar foo
//stream/test2/undo/foo#1 - integrate from //stream/test2/undo/bar#2,#5
C:\Perforce\test\undo>p4 interchanges bar foo
Change 251 on 2021/06/25 by Samwise#Samwise-dvcs-1509687817 'edit'
Change 252 on 2021/06/25 by Samwise#Samwise-dvcs-1509687817 'fake undo'
What if I want to fix this after the fact? You mentioned that the stream was already copied up -- with a normal copy, there is no metadata record of this if the files were already identical (due to some sort of tricky operation like this). That is, even though integrate sees outstanding revisions, copy says "up-to-date":
C:\Perforce\test\undo>p4 copy -n bar foo
File(s) up-to-date.
In most situations this doesn't matter because you don't copy and merge in the same direction, and so copy biases toward not creating extra revisions for no good reason. In the event you do want the records to be updated so that copy and integrate agree with each other, though, you can do a copy with the -f flag, which tells it to create new revisions for the sole purpose of integration credit:
C:\Perforce\test\undo>p4 copy -f bar foo
//stream/test2/undo/foo#1 - sync/integrate from //stream/test2/undo/bar#2,#5
C:\Perforce\test\undo>p4 submit -d "recordkeeping copy"
Submitting change 253.
Locking 1 files ...
integrate //stream/test2/undo/foo#2
Change 253 submitted.
C:\Perforce\test\undo>p4 interchanges bar foo
bar - all revision(s) already integrated.
The copy -f operation will still do nothing if the files are identical and the credit is fully up to date:
C:\Perforce\test\undo>p4 copy -f bar foo
File(s) up-to-date.
so it's safe to use in non-edge cases as well.
Now, if you don't have any control over any of this, and you just want your script to not report changelists when the two streams are identical by content even if they aren't fully up to date by credit: do p4 copy -n before you do p4 interchanges, and if it reports "up to date", then for your purposes you can just treat it as p4 interchanges reporting the same thing.

Perforce, can submitted changes be shelved?

P4 version... Proxy version: P4P/LINUX26X86_64/2013.2/821990 (2014/04/08)
Let's say I made a bunch of changes and some adds, all in the default CL, then "p4 submit"ted them . Let's say the CL generated was 12345. Then I realized that I forgot a file, made that change, submitted it and that CL is 12346. After all this is done, someone wants me to duplicate that work on another branch. Would have been nice if I shelved the changes that are in 12345 and 12346 but I didn't.
Is there a way to create a new changelist that = 12345 + 12346, which is something that I can shelve and then bring into that other branch ?
Thanks!
Technically you can do this with shelves and a lot of manual work, but what you're describing is what p4 integrate is for.
p4 integ source_branch/...#12345,12346 target_branch/...
p4 resolve -am
The change to target_branch (which consists of everything you did in changes 12345 thru 12346 on source_branch) is now pending in your workspace -- you can either p4 shelve it or just p4 submit it directly.

Perforce: Propagate changes from a file to another

How can I take changes from a file that I have in my depot and apply it to a file in my current workspace.
Consider the following scenario.
I have a branch A where I have submitted some changes to files a1, a2 and a3. The change number associated for this submission is 123.
Now I am in another branch B that I am currently working on. I have to take the changes of file A/a1 that I made as a part of change number 123 and apply it to B/a1.
I tried using perforce-integrate, but I am not able to make it work.
To propagate all of change 123 from A to B:
p4 integ A/...#123,123 B/...
p4 resolve -am
p4 resolve # (if needed)
p4 submit
To propagate ONLY a1#123,123:
p4 integ A/a1#123,123 B/a1
p4 resolve -am
p4 resolve # (if needed)
p4 submit
If any part of this does not work, an error message will be displayed indicating what you need to correct in order to make it work.

How do I checkout a perforce shelf at the changelist it was shelved at?

I have a perforce shelf that's CL 1000. It was shelved by someone else at some unknown CL X.
I'm at CL 2000. I'd like to sync to whatever X is and unshelf 1000 so my code is exactly the same as when it was shelved. How do I do this?
Unfortunately, there's no guarantee that their entire client workspace was synced to just one changelist when they shelved. In the extreme case, they could have synced each file at a different change number.
That said, they were probably synced to one point in time, and you can extrapolate this from the revision numbers of the files in their shelf.
$ p4 files #=1000
//depot/foo/bar.txt#3 - edit change 1000 (text)
//depot/baz/quux.c#5 - edit change 1000 (text)
The revision numbers after the filenames indicate the revision of each shelved file that the user synced before opening them for edit.
Then, you can run p4 files with each of the file paths and revisions to get change numbers:
$ p4 files //depot/foo/bar.txt#3 //depot/baz/quux.c#5
//depot/foo/bar.txt#3 - edit change 983 (text)
//depot/baz/quux.c#5 - edit change 998 (text)
Pick the largest of the change numbers from the second command, and try syncing your client to that.
Caveats to the above
Even if we assume they synced to a single point in time, the above isn't foolproof. It only tells us they synced to a change after or including 998 and before 1000.
Let's say they synced to change 999. Their client workspace might have looked like this:
$ p4 have
//depot/an/otherfile#7 - /home/user/a/an/otherfile
//depot/foo/bar.txt#3 - /home/user/a/foo/bar.txt
//depot/baz/quux.c#5 - /home/user/a/baz/quux.c
Let's further say that it was change 999 that updated otherfile to revision 7, and that change 999 only contained otherfile.
Since otherfile was never shelved, and the latest shelved revision above came from change 998, you can't conclude based on the shelf whether the client workspace was synced to change 998 or change 999.
The even bigger caveat is that this all falls apart if they synced different files to different change numbers, but usually people don't do that.

How can I see a unified log of changes to a set of files in perforce?

I'm new to perforce, coming from a history of cvs->svn->git. I'm having a difficult time seeing a compact representation of the most recent changes impacting a set of file. For instance, if I go to a directory and type:
% p4 filelog .
It doesn't do anything useful. More interesting is
% p4 filelog *
However this shows me the change history of every file individually. I'd rather see a unified view of changes in a format showing: change number, submit message, changed files for the most recent N submits.
You can almost get this with:
p4 changes -lt [file[RevRange]...]
This will show you the changelists that affected the files in question. It doesn't show which files were affected by each change, however. You could write a script that took the output of p4 changes and used p4 describe -s to get the file listing for each changelist.
Note that p4 changes includes pending changes by default. Add -s submitted for only submitted changelists. There are other flags to narrow it down further, like -u username and -m max (to limit the number of changelists returned -- it returns newest first).
To list the files that have changed between your #start,#stop times,
p4 -c WORKSPACENAME files //Path/You/Care/About/...#2013/03/20:13:40,#2014/06/016:17:00

Resources