Moving uassets without destroying Perforce file history - an alternative approach.

This question was created in reference to: [Any way to move uassets without destroying Perforce file [Content removed]

Hey Epic,

I apologize in advance for creating another thread on this topic. I understand that the original question was permanently closed, but we found a workaround and we wanted your opinion on whether it would backfire.

I read Cody’s answer and the summary of the last time you guys investigated - which no doubt is a fair number of years ago by now! But I find it interesting that the conversation only covers “p4 move”. I was investigating “p4 integrate” instead, and I didn’t understand why the “p4 integrate” command wouldn’t work, since it is already called via SourceControlHelpers::BranchPackage in FAssetRenameManager::PerformAssetRename. So it got me to run it as a test in perforce - go through the same process that Unreal goes through:

  • Check out original file
  • Save the new renamed file
  • Mark it for add
  • Branch it

Notable is that the branch command passes, but like many have noticed - the branch action P4 history is not there.

So it got me thinking about what ordering P4 would require to ensure the history was kept, and I found the following minor reorder/change worked fine:

  • Check out original file
  • Branch the original file to the new location
  • Check out the new file (since the new file shouldn’t be a bit copy, it needs additional changes by the Editor)
  • Save the new file on top of the earlier copied writable file
  • Resume as before (although the later call to BranchPackage could interfere)

To summarize, our (semi-pseudo) changes are:

//AssetRenameManager.cpp

//FAssetRenameManager::PerformAssetRename

for each AssetToRename

BranchPackage(Asset);

SourceControlHelpers::CheckOutFiles(BranchedAssets);

FEditorFileUtils::PromptForCheckoutAndSave();

//PerforceSourceControlState.cpp

//FPerforceSourceControlState::CanCheckout

//Technically EPerforceState::Branched is also read-only, and you are allowed to check out a Branched file.

const bool bIsInP4NotCheckedOut = State == EPerforceState::ReadOnly || State == EPerforceState::Branched;

We’ve had a few test scenarios with this and it seems to be working fairly well. We do have the following known issues:

- History from the Editor does not work until the renamed file is submitted. Annoying, but it really is a P4 limitation (filelog won’t work on files that have not yet been submitted).

- Unreal Engine does a lot of P4 batching for various scenarios. I’m using batching for CheckOutFiles (instead of CheckOutFile after each call to branch), but would be nice to have batching for BranchPackage too.

- We made some minor changes to the RenamingSlowTask. The branching takes long so I steal some time from elsewhere to be able to update the task after each branch.

- With this change, it exposed an issue in SBlueprintRevisionMenu::OnSourceControlQueryComplete. The iteration here is purely on history, without taking branches into account like “Right click on asset -> Revision Control -> History” does. The aesthetic fix is straightforward (check if there is a branch, and if so also iterate over the branch and its history - and keep doing so until no more branches/revisions). Unfortunately from what I saw in OnDiffRevisionPicked, it uses the file name from the blueprint object (instead of by parameter from RevisionInfo), so changes aren’t as non-trivial anymore.

- Renaming onto a file that was previously deleted in P4 ends up in a strange state where the renamed/‘revived’ file ends up as a delete of a deleted file. I would fix this, I just haven’t looked into it yet.

I was running low on characters, but I left all my changes to the two functions mentioned so others can try them if maintaining history is worth the known issues. I decided against a pull request since the question was permanently closed and I wasn’t sure whether you wanted to approach the problem with integrate instead. Thoughts?

Steps to Reproduce

  • Boot the editor.
  • Find a .uasset.
  • Right click and rename.
  • Submit files.

Note that when you view the history of the new renamed file in Perforce, the file has no history. The result is the same when checking history in the Editor, no history is visible. Weirdly - when you view revision graph, you can see previous iterations of that file.

Hi Bram,

Thanks for reaching out. I asked around about this and I think this should have been addressed for 5.6 - which you should be able to try using the preview version. The expected behavior right now is that the rename is tracked as a branch for the actual asset (while the redirector may be treated as an add or edit). This did involve some re-ordering in the functions you mentioned.

Let me know if you have any questions after trying out the flow or looking at the code for UE 5.6.

Thanks,

Aditya Ravi Chandran

Here is a recent support question that describes the same problem, with the fix in the replies: [Content removed]

Hi Aditya,

Thanks for the answers! I’ll take a look through the changes on 5.6 and see if I can get them into our codebase before we do the full upgrade. Thank you so much!