Reverting a perforce changelist
Indeed, when I design my killer language, the identifiers "foo" and "bar" will be reserved words, never used, and not even mentioned in the reference manual. Any program using one will simply dump core without comment. Multitudes will rejoice.
-- Tim Peters
Introduction
Sometimes you wind up with changes in your source control system that shouldn't be in there, or you hit the submit button in perforce when you really meant just update the description. Anyways, you find yourself with a changelist that you want to roll back. If you're fast enough and noone manages to check in stuff on top of your changes this can be quite easy. There are several nifty sync options to changelists, to files only in changelists and the previous revision in the currently selected changelist. Even so, there is a little bit of work involved when you do this, as you need to then need to open the files for open and then resolve them automagically to accept yours.
Tada! Python!
A long while ago, I think on one of the first projects I wrote with perforce I had this nifty script that could revert changelists for me. I've forgotten what ticked me off that particular time and inspired me to write it, but it turned out to be pretty easy. Of course that script is now long gone. I recently ran into the same problem and realized that I had neither script nor an easy way in perforce to pull this off. So I wrote a new incarnation of the script. This time bigger! Better! More bugs! Eh. Ok, maybe more bugs since it tries to be smarter. And we all know how that goes... the road to hell is paved with seemingly nifty and smart scripts. With the risk of fire and brimstone and revert mayhem, here is the script in all it's glory.
The script is really not intended to be used as is on the commandline, although there is nothing stopping you. The real power comes from the built in hooks perforce have to add context sensitive commands to p4win, our favourite application. If you go in and add the following to the Tools->Customize menu (after you click Add) you will then have a very handy tool in the context menu like this.
In closing.
Power to the people. Although with power there also comes responsibility. Computers just allows us to make our mistakes bigger, better and faster. In fact you can probably cause a lot of mayhem with this script if you don't think before you submit. So be careful. That said, it reduces this operation from maybe a couple of minutes for a large changelist to a couple of seconds depending on your perforce server's speed.
Resources
- Practical Perforce, a pragmatic take on how to manage and do common operations in perforce the way it was intended. Go with the flow and read it!
Update 9/11/07
I updated the script with changes kindly submitted by Matt Zimmer, with the permission of Intuit. Some refactoring and features like:
- Changed default from overwrite to require manual resolve if later edits made to a file (you want to roll 28 back to 27 but there is a 29 in the depot).
- Added force flag to force overwrite (27 would overwrite 29 in the above scenario).
Thanks Matt for those changes! Now we can undo changes in perforce with ease :).
Update 11/8/07
Small update to support filenames with spaces in them.
2008-05-26: Update
I've started a new open source project for all the perforce stuff I've written. Ironically it is hosted on a subversion server. You can see it over here: http://code.google.com/p/p4scripts.
Thanks, Jim.
For ages I was going to write a script to do this. Now I don't need to :)
Haha, glad to be of service. I hope there are no bad bugs in there, although I'm going to eat my own dogfood and use it myself next time I find myself needing to revert large things in a hurry. So we'll see.
Just trying out the new comment interface. Note that there has been an update to the page, with fixes to the script itself (p4revert.py). Thanks to Matt Zimmer for the fixes.
The link to p4revert.py is broken. No biggie, but the comment block and copyright isn't in the text block above.
Great script, thanks man.
Chris,
Thanks for the report. I've fixed the broken link. It was another effect of the big server move. The copyright notice was intentionally taken out of the listing on the webpage since it cluttered the page needlessly, I assumed that (if the link was working) people took the ready to go file instead of copy-past the code from the webpage (I've had problems with indenting etc when doing that in the past). Thanks for the report!
Thanks for the script.
I have a problem, or maybe it's a feature request. I have integrated to a branch that I didn't want to integrate to, and would like to revert the change. For files deleted or added, this script works fine - but if the files have been edited/integrated then nothing happens.
Graeme,
That sounds suspiciously like a bug. IIRC when you integrated A.cpp into B.cpp and then run this script, it should just revert B.cpp one revision. Let me take a look and see what is happening...
Graeme,
Ok. I could have sworn that the action that got logged in the record was 'branch', but after installing a new version of perforce I saw that the action was now called 'integrate'... hm. Oh, well. It's fixed. Download the new version of the script and try it out! Sorry for the hassle.
Yeah, it's working fine now. Thanks very much!
Hi, Jim,
This script looks fantastic, but when I try to use it, I get the following in the p4Win console:
TOOL: 20:50:31 C:\WINDOWS\system32\cmd.exe /c p4revert.py -c mrubin_integrate -p pf1.dt.corp.yahoo.com:2014 -u mrubin 85576
STATUS: 20:50:31 SyntaxError: invalid syntax (p4revert.py, line 126)
I just copied the source from your web page, so line 126 corresponds to
print 'Error parsing arguments'
I don't actually know Python, so it's a bit hard for me to figure out what's up, although I guess there's something wrong with parsing the arguments. But they look fine to me in the console output. Also, if I run from the command line as
p4revert.py -v -c mrubin_integrate -p pf1.dt.corp.yahoo.com:2014 -u mrubin 85576
I get the same error.
I must be doing something silly wrong, but I don't know what it is?
Thanks for any help, and thanks for building the tool!
-- Markg
Hi Mark,
Sorry about this, python is actually white space sensitive and what I suspect happened is that you have copied the actual text of the script here on the page and saved it down to a text file? That might wind up with all sorts of problems, for example, the line that you list 126, in the original script it should be 151 that has the "Error parsing Arguments" text.
Can you try to right click on the link beneath the script text that has the link to p4revert.py and select "Save As" in your browser? That should hopefully download the script in working order for you. What kind of browser do you use?
Let me know if it didn't work!
Cheers,
Jim
Thanks for the wonderful script Jim
I am newbie in Python and am facing a problem. I have installed Python and copied your script and imported it. But when I click RevertChangelist it says unable to run p4revert.py
Ah, well, you most probably have to put the absolute path for the script in the dialog box there, unless you've got whatever path you put the p4revert.py in your PATH environment variable *and* you had the python interpreter register itself as a handler when you installed your python distribution. But just sticking a reference to the absolute path in the above dialog (Edit Tool) should do it.
Sorry to bug you again
I have put the absolute path . Still it doesn't work.
Nice script. And your scripts have got me going with python and p4... thank you! Note that p4v now also has custom tools so it's not just a p4win thing.
Regarding the absolute path thing for Byomkesh... I'm assuming that Byomkesh has python installed or on the computer but perhaps .py is not associated with python.exe. You can try putting the absolute path to your python.exe as the tool and the absolute path to the python script as the first argument.
My own request (unless I get "around to it"!-) is that there would be a way to do this on selected files with options for what revision/changelist to revert back to/from etc.
In general, a lot of our reverts are of the form where a big changelist has a few files that were accidently included in the check in, so only a few files (of possibly many) need to be reverted. although one could sit there and wait for it to churn through reverting the whole changelist and then revert all but what is desired, it's cumbersome...
I don't like that the custom tools doesn't allow more than one selection parameter (eg %d %c) since several commands are of the form -c CL filelist, so it would be handy to be able to pass this type of thing in from p4v/p4win to a script.
Great script - thanks!
One issue I have just come across - rolling back a "branch of revision 1" results in a "delete". This is unfortunately NOT an "unintegrate my file" and results in future integrations at the same revision (i.e. reinstating) for that file failing.
i.e.
- For a file at revision #n in A branch
- For a file that does not yet exist in B branch
- Branch file from A branch to B branch
- B results in an 'branch add'. Revision #1
- Revert this file from B results in a delete in B. Revision #2
- Reintegrate same file from A at revision #n.
- Expected behaviour is that file in B should reappear.
- Nothing doing - file in B is at a more advanced revision than that coming from A (#n => #1 in B)
Hope this makes sense.
I'll take a look and see what I can figure out.
Cheers,
Will.
It seems that is the expected behavior... "reverting" does leave history... you can't change that.
So, at least in perforce, to reintegrate on top you have to use a -d flage on the integration to say that you acknowledge the previous delete.
"Reverting a change" does not mean erasing history, it means redo history in the present!-)
Hope that helps!
Peter
Will,
I think there probably something in what yamo says, if you are using the GUI then the default settings of the integration dialog are not always the right ones. Could you open a ticket on the google code site, and send over the exact command lines that you are using? (You can turn them on in the gui, under options,advanced)
/j
Nice script! I'm glad I stumbled upon it.
However, what I was hoping to find was a "reintegrate" script for when someone inadvertantly checks in a changelist that clobbers your changes, e.g. get revision for each file part of your change list, check out, get latest revision, resolve.
I believe you can already do this by integrating a single revision... but you'd probably have to force it (-f) since it would think that the changes had already been integrated (which they were, the other guy clobbered them, so this makes sense).
Thanks for the script! I'm trying it out and I'm receiving an error from the Marshall library. I don't know python so i'm not sure what's going on, any ideas? It runs a bunch of calls successfully and then dies on the first file it needs to revert in the current directory:
...
2009-10-09 09:44:08,857 DEBUG : p4 -G edit "//path/to/file/here"
Traceback (most recent call last):
File "/path/to/p4revert", line 219, in
sys.exit( main(sys.argv[1:]) )
File "/path/to/p4revert", line 205, in main
revertChangelist( changelistNumber, force )
File "/path/to/p4revert", line 128, in revertChangelist
backRevision(name, revision, force)
File "/path/to/p4revert", line 76, in backRevision
syncDoActionAndResolve(name, "edit", int(revision), force)
File "/path/to/p4revert", line 91, in syncDoActionAndResolve
p4( '%s "%s"' % (action, name) )
File "/path/to/p4revert", line 47, in p4
entry = marshal.load(stream)
ValueError: bad marshal data