This question already has answers here:
Determining the last changelist synced to in Perforce
(10 answers)
Closed 8 days ago.
In my perforce workspace, I run these 3 commands:
# 1
p4 changes -m1 ./...
Change 11111111 on 2020/01/01 by abc#def 'Jan 1'
#2
p4 changes -m1
Change 11112222 on 2020/02/01 by abc#def 'Feb 1'
#3
p4 changes -m1 //...
Change 11113333 on 2020/03/01 by abc#def 'Mar 1'
All three commands result in 3 different outputs
How do i interpret the results?
I wanted to know what is the tip of my local workspace (In analogy to HEAD in git)
But this seems to be very convoluted in Perforce
Thanks in Advance :)
Firstly if you are interested only with submitted changes (without pending changelists) you could specify -s submitted option to your command line.
Your local workspace may not include whole repo, just some view of it, defined by workspace mapping.
If you want to get global head revision you may use:
p4 changes -m 1 -s submitted
If you want to get head revision of current directory:
p4 changes -m 1 -s submitted ./...
More you can find out in p4 help changes
Related
Consider the following revisions of a file:
branch -1---2---
/
/
main 100--101-102--103---104---
I am currently in my branch and the file is synced to revision 2. I know that p4 has kept the history of the file, because I used merge and not copy, and indeed the history shows revisions previous to 103 (inclusive) when I look at the history of the file and check the option "Follow branch actions".
I would like to roll it back to revision 103 or before. Is this possible?
Answers for p4v preferred, but I'll take command line statements if that's the only way to do it.
The copy command is the best way of doing this:
p4 copy main#103 branch
Another option would be to use integ -f:
p4 integ -f main#103 branch
p4 resolve -at
One benefit of copy is that if you're doing this across a bunch of files (e.g. main/...#2018/01/01 to get all of main as of Jan 1) and some of them are already identical to the rev you're copying from because they haven't changed in that time, copy will leave them alone, which makes the result less noisy.
Background
I have a "mainline" depot and a "beta" branch in Perforce (using simple branches: no streams, etc).
I would like to merge the latest code from "mainline" to my "beta" branch. I have to do this about once every day, and there are about 100+ commits/submissions to the "mainline branch" every day.
Normally, I would do something like so:
p4 integ //prod/mainline/... //prod/beta/...
cd $(p4 where //prod/beta/... | cut -d ' ' -f3 | sed 's/\.\.\.$//g')
p4 resolve ./...
Problem
However, we have an annoying hourly build process that updates version numbers in various Makefiles, build scripts, etc; that updates version/branch numbers, and is checked in to Perforce using a "dummy" account (i.e. dummy_user) by our build servers. This is done across all branches, causing any merge operation to have arbitrary conflicts.
This version number submission now prevents my p4 integ/p4 resolve operation from completing cleanly, and I have to hand-merge all of these files affected by the "version number update operation". I would like to just have to hand-merge actual code changes, rather than this version number nonsense.
Question
Is there a way to p4 integ a set of change-lists not yet present in the branch (but present in main/another-branch), excluding a user? I could always do something like:
for i in $(p4 changes //prod/mainline/... | grep -v dummy_user | cut -d ' ' -f2)
do
p4 integ //prod/mainline/...#${i},${i} //prod/beta/...
done
However, I don't have an automated way to get a list of all change-lists that:
Exist in mainline...
But haven't yet been merged/integrated into beta...
And aren't authored by dummy_user.
How can I accomplish this?
Sounds like you've found a solution that works for you, but FWIW here's what I'd do:
0) Make a branchspec since that makes this next part easier:
p4 --field "View=//prod/mainline/... //prod/beta/..." branch -o prod-main-beta | p4 branch -i
1) Ignore the robo-commits (I assume you want to just leave these things alone):
p4 -Ztag -F #=%change% ichanges -u dummy_user -b prod-main-beta | p4 -x - integ -b prod-main-beta
p4 resolve -ay
p4 submit -d "Begone, robo-cruft!"
2) Do the "real" integrate. If you find yourself still having to pick around the "dummy" changes, try the -Rs option -- that might give you more merges to do but it will bend over backwards to make sure those merges don't include anything you've already integrated.
p4 integ -b prod-main-beta [-Rs]
p4 resolve [-am]
p4 submit
Optional 3) Improve your build tooling so that the version info is located in a dedicated file, and other build files link to it. Then you can exclude your version file from your branch specs, or just always ignore changes to it without having to cherry-pick, or whatever. Here's a real-world example: https://swarm.workshop.perforce.com/files/guest/perforce_software/p4/2015-1/Version
I have a branch in my depot that I want to copy to a parallel location that does not currently exist in the depot. (i.e. I currently have \depot\rev6.2... and I need to create another branch at \depot\rev6.2b...) There are 2 things I would like to also happen:
First, I need the changelist history from rev6.2 to copy over to rev6.2b. When I have tried using the integrate feature, I have a new branch in the depot, but the history is blank (only 1 entry from the CL I submitted to create the branch).
Second (if possible) I would like to find a quick way so that if new changes are made in rev6.2, I can easily apply them to the rev6.2b branch as well.
I am a pretty basic P4V user (2011.1), so the more details the better. Thanks in advance for any help!!
You need to enable branch history. Click the icon I've circled in red, and select "Follow Branch Actions" in the dropdown.
Regarding your second question, if you want to bring over changes from the original branch, you can just run integrate a second time. Perforce tracks the integration history, so it knows when the branch was created, and what changes have been integrated since then (if any).
Perforce keeps all the integration history, as others already mentioned so everything from the 'rev6.2b' branch will have it's history traced to the 'rev6.2' branch. The P4V Revision Graph shows all of this history visually. On the command line the 'p4 filelog' or 'p4 filelog -i' commands, for example:
$ p4 filelog //depot/rev6.2b/...
//depot/rev6.2b/bar
... #1 change 12179 branch on 2016/02/25 by super1#super2015.2 (text) 'copy'
... ... branch from //depot/rev6.2/bar#1
//depot/rev6.2b/foo
... #1 change 12179 branch on 2016/02/25 by super1#super2015.2 (text) 'copy'
... ... branch from //depot/rev6.2/foo#1
The output shows the files in rev6.2b were branched from rev6.2 directory.
I am not sure which version and OS of the Perforce server and P4V client you are using but here is some feedback.
Regarding if new changes are made in rev6.2, to easily apply them to the rev6.2b branch also you can use a change-commit trigger to do that.
You could create a branchspec that has a view that maps all the changes from 'rev6.2' to 'rev6.2b' and then use the branch spec in the copy or integ command.
See Admin Guide: Change-commit Triggers
https://www.perforce.com/perforce/doc.current/manuals/p4sag/chapter.scripting.html#scripting.triggers.submits.commit
EXAMPLE BRANCHSPEC
Here is a view of a branch spec named 'master6.2copy'
View:
//depot/rev6.2/... //depot/rev6.2b/...
EXAMPLE
Here is *.bat file showing the content of a trigger script. (This is not an official Perforce script, just an example that can be tweaked.)
The first line below can also be instead:
p4 -p localhost:1666 -u myuser -c mywksp copy -b master6.2copy
#echo off
::
:: Example: The following change-commit trigger is an MS-DOS batch file
:: This trigger fires only after a changelist submission on a master directory
::
:: Add the following line to your triggers table:
::
:: copymaster change-commit //depot/rev6.2/... "/home/user/scripts/copyrev6-2.bat"
p4 -p localhost:1666 -u myuser -c mywksp integ -b master6.2copy
p4 -p localhost:1666 -u myuser -c mywksp resolve -at
p4 -p localhost:1666 -u myuser -c mywksp submit -d "rev6.2 copy to rev6.2b after changelist"
exit 0
Hope this helps!
Short version:
After branching in P4, how can I find out the "source" changelist of the branch?
Long version:
Let's say I have a main branch of my project at
//project/main/...
The latest changelist submitted here is #123, when I decide to create a branch for release 1.0 in
//project/1.0/...
From P4V, a new changelist is created (say #130), resolved and submitted.
From the CLI, it would look something like this:
p4 integrate -c 123 -o //project/main/... //project/1.0/...
p4 submit
Later, I look at the changelists under //project/1.0, and see the #130 changelist containing a lot of branched files.
How can I find out the changelist no. that this was originally branched from (that is, #123) ?
p4 changes will display a list of submitted changelists, optionally filtered to a specific path.
p4 changes //project/main/...
Change 123 ... 'Very last change.'
Change 122 ... 'Next-to-last change.'
Change 100 ... 'Only two changes to go...'
...
No surprise there, but, as you've found, p4 changes is less helpful when you integrate all those changes in a single change:
p4 changes //project/1.0/...
Change 130 ... 'Integrated everything from main.'
The trick is to use the -i option which includes any changelists integrated into the specified files.
p4 changes -i //project/1.0/...
Change 130 ... 'Integrated everything from main.'
Change 123 ... 'Very last change.'
Change 122 ... 'Next-to-last change.'
Change 100 ... 'Only two changes to go...'
...
To get exactly what you want (123) you'll need to write a script which filters the output from p4 changes -i //project/1.0/... to remove any change listed by p4 changes //project/1.0/... (and then take the most recent remaining change).
(When exploring, I frequently also find the -m max option useful. This limits changes to the 'max' most recent. This helps your output not flow offscreen when there are many changes.)
I don't know of any simple command that performs what you would like to do. If you are willing to script a little bit and the command doesn't have to execute fast you could perhaps try to script something like the following for all branched files:
Find the source file/revision for a target file.
p4 filelog //project/1.1/foo.bar#1
//project/1.1/foo.bar
... #1 change 6416 branch on 2009/07/10 by foo#bar (text) 'Release 1.1'
... ... branch from //project/main/foo.bar#1,#2
Get the change list at which the source file/revision was submitted.
p4 fstat //project/main/foo.bar#2
... depotFile //project/main/foo.bar
... headAction edit
... headType text
... headTime 1201771167
... headRev 2
... headChange 5353
... headModTime 1201770971
Repeat for all files in branch and select the highest change no (headChange above), which should be the latest change submitted to the parent before branching for that specific file. You could get a complete listing of all branched files using e.g. "p4 files //project/1.0/...#1".
(or perhaps take the easy way out and ask Perforce support)
Since none of the answers thus far provide the code for finding the source or root changelist of a branch, I thought I'd provide a one-liner to do just that. This approach is based on #Cwan's suggestion, and will print the "parent" changelist from which the branch was created. The FIRST_BRANCH_CL argument needs to be replaced with the branch creation changelist (i.e. the first changelist submitted to the new branch). As a concrete example, replacing FIRST_BRANCH_CL with 130 from the original question, this one-liner would output 123.
p4 describe -s FIRST_BRANCH_CL | perl -lne 'if(/^\.\.\. (.+#[0-9]+) .+$/) {print quotemeta $1}' | xargs p4 filelog -m1 | perl -lne 'if(/^\.\.\. \.\.\. branch from (.+#[0-9]+)/) {print quotemeta $1}' | xargs p4 fstat | perl -lne 'if(/^\.\.\. headChange (\d+)/) {$MaxCL=$1 if($1 > $MaxCL)} END {print $MaxCL}'
Short answer:
Use the Revision Graph in P4V is step back through time and investigate the integration history. Video on the Perforce website.
I have successfully used the revision graph on branches with thousands of files to track when an particular change was integrated into a branch. That is why I recommended it and linked to a training video as most people under-estimate it because they do not know how to use it.
Long answer:
... [Removed]
UPDATE: As the Revision Graph apparently is unfeasible, you can perhaps solve this using a process/policy, i.e., when you perform the integrate, add a note in the description "Branched # CL 123". We used this approach ourselves when integrating from a trunk to release lines.
If you use the history tab in p4v it will show you all changelists submitted against a branch, so look at this for
//project/1.0/...
once you have found the oldest submitted changelist, then on any one the files in that changelist view the Revision Graph for it, this will show you the branch that the file (and the rest of the files) were integrated from.
I'll see if I can come back with the p4 commands to do the same thing.
Updated Answer: I think this will work. Try this:
p4 interchanges from_branch to_branch
This will show unintegrated changes from your main branch to your release branch. I believe you can use the top changelist number minus 1 to find your source changelist. interchanges is an undocumented Perforce CLI feature. To find out more, type p4 help interchanges to find out more about this command.
Again, I think this will work. There may be some special cases where it will not, but it's my best guess to a tough and important problem.
"p4 integrated" worked for me. Look for "copy from" in the description
This question already has answers here:
Mercurial: how to amend the last commit?
(8 answers)
Closed 5 years ago.
I am currently using TortoiseHg (Mercurial) and accidentally committed an incorrect commit message. How do I go about editing this commit message in the repository?
Update: Mercurial has added --amend which should be the preferred option now.
You can rollback the last commit (but only the last one) with hg rollback and then reapply it.
Important: this permanently removes the latest commit (or pull). So if you've done a hg update that commit is no longer in your working directory then it's gone forever. So make a copy first.
Other than that, you cannot change the repository's history (including commit messages), because everything in there is check-summed. The only thing you could do is prune the history after a given changeset, and then recreate it accordingly.
None of this will work if you have already published your changes (unless you can get hold of all copies), and you also cannot "rewrite history" that include GPG-signed commits (by other people).
Well, I used to do this way:
Imagine, you have 500 commits, and your erroneous commit message is in r.498.
hg qimport -r 498:tip
hg qpop -a
joe .hg/patches/498.diff
(change the comment, after the mercurial header)
hg qpush -a
hg qdelete -r qbase:qtip
Good news: hg 2.2 just added git like --amend option.
and in tortoiseHg, you can use "Amend current revision" by select black arrow on the right of commit button
I know this is an old post and you marked the question as answered. I was looking for the same thing recently and I found the histedit extension very useful. The process is explained here:
http://knowledgestockpile.blogspot.com/2010/12/changing-commit-message-of-revision-in.html
Last operation was the commit in question
To change the commit message of the last commit when the last mercurial operation was a commit you can use
$ hg rollback
to roll back the last commit and re-commit it with the new message:
$ hg ci -m 'new message'
But be careful because the rollback command also rolls back following operations:
import
pull
push (with this repository as the destination)
unbundle
(see hg help rollback)
Thus, if you are not sure if the last mercurial command was a hg ci, don't use hg rollback.
Change any other commit message
You can use the mq extension, which is distributed with Mercurial, to change the commit message of any commit.
This approach is only useful when there aren't already cloned repositories in the public that contain the changeset you want to rename because doing so alters the changeset hash of it and all following changesets.
That means that you have to be able to remove all existing clones that include the changeset you want to rename, or else pushing/pulling between them wouldn't work.
To use the mq extension you have to explicitly enable it, e.g. under UNIX check your ~/.hgrc, which should contain following lines:
[extensions]
mq=
Say that you want to change revision X - first qimport imports revisions X and following. Now they are registered as a stack of applied patches. Popping (qpop) the complete stack except X makes X available for changes via qrefresh. After the commit message is changed you have to push all patches again (qpop) to re-apply them, i.e. to recreate the following revisions. The stack of patches isn't needed any, thus it can be removed via qfinish.
Following demo script shows all operations in action. In the example the commit message of third changeset is renamed.
# test.sh
cd $(dirname $0)
set -x -e -u
echo INFO: Delete old stuff
rm -rf .hg `seq 5`
echo INFO: Setup repository with 5 revisions
hg init
echo '[ui]' > .hg/hgrc
echo 'username=Joe User <juser#example.org>' >> .hg/hgrc
echo 'style = compact' >> .hg/hgrc
echo '[extensions]' >> .hg/hgrc
echo 'mq=' >> .hg/hgrc
for i in `seq 5`; do
touch $i && hg add $i && hg ci -m "changeset message $i" $i
done
hg log
echo INFO: Need to rename the commit message on the 3rd revision
echo INFO: Displays all patches
hg qseries
echo INFO: Import all revisions including the 3rd to the last one as patches
hg qimport -r $(hg identify -n -r 'children(2)'):tip
hg qseries
echo INFO: Pop patches
hg qpop -a
hg qseries
hg log
hg parent
hg commit --amend -m 'CHANGED MESSAGE'
hg log
echo INFO: Push all remaining patches
hg qpush -a
hg log
hg qseries
echo INFO: Remove all patches
hg qfinish -a
hg qseries && hg log && hg parent
Copy it to an empty directory an execute it e.g. via:
$ bash test.sh 2>&1 | tee log
The output should include the original changeset message:
+ hg log
[..]
2 53bc13f21b04 2011-08-31 17:26 +0200 juser
changeset message 3
And the rename operation the changed message:
+ hg log
[..]
2 3ff8a832d057 2011-08-31 17:26 +0200 juser
CHANGED MESSAGE
(Tested with Mercurial 4.5.2)
In TortoiseHg, right-click on the revision you want to modify. Choose Modify History->Import MQ. That will convert all the revisions up to and including the selected revision from Mercurial changesets into Mercurial Queue patches. Select the Patch you want to modify the message for, and it should automatically change the screen to the MQ editor. Edit the message which is in the middle of the screen, then click QRefresh. Finally, right click on the patch and choose Modify History->Finish Patch, which will convert it from a patch back into a change set.
Oh, this assumes that MQ is an active extension for TortoiseHG on this repository. If not, you should be able to click File->Settings, click Extensions, and click the mq checkbox. It should warn you that you have to close TortoiseHg before the extension is active, so close and reopen.
EDIT: As pointed out by users, don't use MQ, use commit --amend. This answer is mostly of historic interest now.
As others have mentioned the MQ extension is much more suited for this task, and you don't run the risk of destroying your work. To do this:
Enable the MQ extension, by adding something like this to your hgrc:
[extensions]
mq =
Update to the changeset you want to edit, typically tip:
hg up $rev
Import the current changeset into the queue:
hg qimport -r .
Refresh the patch, and edit the commit message:
hg qrefresh -e
Finish all applied patches (one, in this case) and store them as regular changesets:
hg qfinish -a
I'm not familiar with TortoiseHg, but the commands should be similar to those above. I also believe it's worth mentioning that editing history is risky; you should only do it if you're absolutely certain that the changeset hasn't been pushed to or pulled from anywhere else.
Rollback-and-reapply is realy simple solution, but it can help only with the last commit. Mercurial Queues is much more powerful thing (note that you need to enable Mercurial Queues Extension in order to use "hg q*" commands).
I did it this way. Firstly, don't push your changes or you are out of luck. Grab and install the collapse extension. Commit another dummy changeset. Then use collapse to combine the previous two changesets into one. It will prompt you for a new commit message, giving you the messages that you already have as a starting point. You have effectively changed your original commit message.
One hack i use if the revision i want to edit is not so old:
Let's say you're at rev 500 and you want to edit 497.
hg export -o rev497 497
hg export -o rev498 498
hg export -o rev499 499
hg export -o rev500 500
Edit rev497 file and change the message. (It's after first lines preceded by "#")
hg import rev497
hg import rev498
hg import rev499
hg import rev500
There is another approach with the MQ extension and the debug commands. This is a general way to modify history without losing data. Let me assume the same situation as Antonio.
// set current tip to rev 497
hg debugsetparents 497
hg debugrebuildstate
// hg add/remove if needed
hg commit
hg strip [-n] 498
A little gem in the discussion above - thanks to #Codest and #Kevin Pullin.
In TortoiseHg, there's a dropdown option adjacent to the commit button. Selecting "Amend current revision" brings back the comment and the list of files. SO useful.