p4 interchanges showing integrated changelists - perforce

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.

Related

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

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?"

Perforce submit edited source file and branch/integrate/merge/copy from same source file in one changelist

Suppose we have a single text file in 2 branches:
//depot/work/branch1/file.txt
//depot/work/branch2/file.txt
We also have a central source file here that both branches depend on.
//depot/work/ImportantFile.txt
I make local edits to ImportantFile.txt and branch1/file.txt, but I also want to duplicate those edits to branch2/file.txt because ImportantFile.txt now expects all branches of file.txt to conform to a certain specification. As far as I know I have only 2 options, neither of which are ideal:
Manually make the same edits on both files and submit both changes in a single changelist. The problem with this, is that I would like P4 history to know that these files are still 100% integrated, but the history will show that they were edited independently.
Only make edits to branch1/file.txt, submit just this file as well as ImportantFile.txt in one changelist, then immediately integrate the change to branch2/file.txt in a 2nd changelist. Now the problem is that I've broken the build for a minute or two until branch2/file.txt gets the required changes.
How can I edit a file, and directly integrate those edits to another file before I submit those edits to the first file?
First off: you may already know this (and have had to make peace with it for reasons beyond your control) but:
ImportantFile.txt should not be outside of your branching structure. If your versioned files depend on it, it needs to be versioned itself, and that means it needs to exist independently in each branch, because branches are a part of your versioning scheme. Alternatively, maybe file.txt should not be branched, if it's required that it be identical in all branches at all times -- why branch something that's not allowed to diverge? But I suspect that just branching everything is the better solution.
Now for the workaround. (If you can't fix the root cause as described above, you've probably got a lot of this sort of thing in your future.)
p4 copy //depot/work/ImportantFile.txt //depot/work/NotABranch/ImportantFile.txt
p4 copy //depot/work/branch1/file.txt //depot/work/NotABranch/file.txt
p4 submit -d "Not a branch! (wink)"
Make your edits in //depot/work/NotABranch and submit them. Nothing is broken because, as stated, this is not a branch, and so it's exempt from whatever policy it is that forces all branches to move in lockstep. Now you can do:
p4 integ //depot/work/NotABranch/ImportantFile.txt //depot/work/ImportantFile.txt
p4 integ //depot/work/NotABranch/file.txt //depot/work/branch1/file.txt
p4 integ //depot/work/NotABranch/file.txt //depot/work/branch2/file.txt
p4 resolve
p4 submit
The merge history shows that both branches of file.txt were pure merges from a single common source, and so future integrations between the two should recognize that they don't need to be re-merged.

Perforce Changelist and shelve command

I am very new to Perforce and just started using it.
After syncing my code using $p4 sync command i started editing a few files.
$p4 edit file1
$p4 edit file2
$p4 edit file3
These files were getting added to my default changelist. For collaborating with my team i wanted to create a changelist. For creating a changelist i ran $p4 change and removed "file1" from the changelist description. Now when i run $p4 opened. It gives an output similar to this.
//depot/... /file1 edit default change (text)
//depot/... /file2 edit default 111 (text+k)
//depot/... /file3 edit default 111 (text+k)
Now i have the following questions in my mind:
Which changelist am i currently working on is it default or 111 ??
what is the meaning of (test + k)?
When i make changes to file2 and file3 it is getting synced to changelist 111 and when i make changes to file1 it gets synced to default changelist . I am highly confused how is this happening ?
Also one more thing i am confused about is if do $p4 shelve will my changes disappear and will be reapplied only when i run unshelve command for the changelist created ?? Is this similar to git stash and git stash apply ?
It will be great if someone can answer these questions in detail. Any tutorial suggestions for Perforce will also be of great help.
Thanks in advance.
My recommendation for a Perforce tutorial is the Perforce User's Guide. Here's the section on changelists:
https://www.perforce.com/perforce/r15.1/manuals/intro/chapter.working_in_perforce.html#working_in_perforce.working_with_files.changelists
Which changelist am i currently working on is it default or 111 ??
Both! Both of these are pending changelists in your workspace.
what is the meaning of (text+k)?
The thing in parentheses is the "filetype". +k is a "filetype modifier" meaning that keywords (special words like $Id$ and $Revision$ and $Author$ in this file will be automatically expanded to appropriate values when you submit.
When i make changes to file2 and file3 it is getting synced to changelist 111 and when i make changes to file1 it gets synced to default changelist . I am highly confused how is this happening ?
Nothing is getting "synced" anywhere yet -- the pending changelists are just containers that reference the different files. When you shelve or submit, then the files associated with those changelists will get sent to the server and will be accessible by other clients. Since shelve and submit are changelist-level operations, only the files in those changelists are affected -- that's the point of having different pending changelists. You have all of the pending files in your workspace, but you can split up which ones get sent to the server at which times (it's a little like pushing different branches in git, but not -- you can do this on every operation in Perforce even when you aren't branching because each file is versioned individually rather than having the entire tree versioned as one atomic blob).
Also one more thing i am confused about is if do $p4 shelve will my changes disappear and will be reapplied only when i run unshelve command for the changelist created ?? Is this similar to git stash and git stash apply ?
No, p4 shelve only syncs the shelved change on the server with the local files in your workspace -- it doesn't in itself change your workspace. The equivalent of "stashing" would be to p4 shelve and then to p4 revert to wipe out the workspace changes. shelve on its own is a little more like doing a git push to a branch -- you keep your local copy but now it's also on the server (but not part of the "master" history). (It's not exactly the same though -- to be honest if you're brand new to Perforce I'd stick to regular old "submit" in a regular old branch since that's the basic workflow. Sharing work via shelves requires a lot more manual work since each shelf is like its own little mini-branch with no versioning.)

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.

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.

Resources