This is a refactor of the Git LFS 2 plugin by SRombauts, with lessons learned from production that include performance optimizations, new features and workflow improvements.
Either install this into your project's Plugins/
folder, or if you would like to install to the engine,
rename Engine/Plugins/Developer/GitSourceControl.uplugin
to Engine/Plugins/Developer/GitSourceControl.uplugin.disabled
and then install this plugin to the Engine/Plugins
folder.
Please note that we do not provide precompiled binaries at this time, so you will need to use Visual Studio to compile the plugin.
This plugin requires explicit file attributes for *.umap
and *.uasset
, rather than other approaches of using wildcards for the content folder (Content/**
).
See our own .gitattributes
for an example.
You may also want to check out our robust .gitignore
too.
We would highly recommend using HTTPS authentication for your Git repo.
This allows a single credential path to be used, with the robust and fast HTTPS support in LFS.
With Git Credential Manager, authenticating with HTTPS is also much easier, with a GUI available to authenticate with any Git provider.
Config/DefaultEditorPerProjectUserSettings.ini
[/Script/UnrealEd.EditorLoadingSavingSettings]
bSCCAutoAddNewFiles=False
Config/DefaultEditorPerProjectUserSettings.ini
. To enable auto-checkout on modification, which is great for OFPA and other workflows (but requires user attention to excessive locking of content):[/Script/UnrealEd.EditorLoadingSavingSettings]
bAutomaticallyCheckoutOnAssetModification=True
bPromptForCheckoutOnAssetModification=False
[/Script/UnrealEd.EditorLoadingSavingSettings]
bAutomaticallyCheckoutOnAssetModification=False
bPromptForCheckoutOnAssetModification=True
Config/DefaultEditorPerProjectUserSettings.ini
: [/Script/UnrealEd.EditorPerProjectUserSettings]
bAutoloadCheckedOutPackages=True
Config/DefaultEngine.ini
you can set this option to 1
to disable a feature that is unnecessary for Git (for performance):[SystemSettingsEditor]
r.Editor.SkipSourceControlCheckForEditablePackages=1
Epic Games added Status Branches in 4.20, and this plugin has implemented support for them. See Workflow on Fortnite for more information. Here is an example of how you may apply it to your own game.
UUnrealEdEngine
subclass, preferrably in an editor only module, or guarded by WITH_EDITOR
.#include "ISourceControlModule.h"
#include "ISourceControlProvider.h"
void UMyEdEngine::Init(IEngineLoop* InEngineLoop)
{
Super::Init(InEngineLoop);
// Register state branches
const ISourceControlModule& SourceControlModule = ISourceControlModule::Get();
{
ISourceControlProvider& SourceControlProvider = SourceControlModule.GetProvider();
// Order matters. Lower values are lower in the hierarchy, i.e., changes from higher branches get automatically merged down.
// (Automatic merging requires an appropriately configured CI pipeline)
// With this paradigm, the higher the branch is, the stabler it is, and has changes manually promoted up.
const TArray<FString> Branches {"origin/develop", "origin/promoted"};
SourceControlProvider.RegisterStateBranches(Branches, TEXT("Content"));
}
}
Config/DefaultEngine.ini
(make sure the class name is MyUnrealEdEngine
for a class called UMyUnrealEdEngine
!):[/Script/Engine.Engine]
UnrealEdEngine=/Script/MyModule.MyEdEngine
In this example, origin/promoted
is the highest tested branch. Any changes in this branch are asset changes that do not need testing, and get automatically merged down to origin/develop
. This may be extended to involve multiple branches, like origin/trunk
, origin/main
, or whatever you may prefer, where changes may be cascaded from most-stable to least-stable automatically. With this paradigm, changes from less-stable branches are manually promoted to more-stable branches after a merge review.
NOTE: The second argument in RegisterStateBranches
is Perforce specific and is ignored, but is meant to point to the relative content path.
If you decide to implement the status branch code in a editor-only module, ensure the loading phase in the editor module is set to Default
in your .uproject settings, like so: (Otherwise, the editor will likely have difficulty finding your subclass'd UUnrealEdEngine class.)
{
"Name": "MyTestProjectEditor",
"Type": "Editor",
"LoadingPhase": "Default"
}
This feature helps ensure you're not locking and modifying files that are out-of-date.
If a user is on any branch, regardless if it's tracking a branch included in the 'status branch' list, they will be unable to checkout files that have more recent changes on the remote server than they have on the local branch, provided those changes are in a branch in the 'status branch' list.
It's important to only release file locks after changes have been pushed to the server. The system has no way to determine that there are local changes to a file, so if you modify a locked file it's imperative that you push the changes to a remote branch included in the 'status branch' list so other users can see those changes and avoid modifying a stale file. Otherwise, you'll want to keep the file locked!
Additionally, if you're switching back and forth between two or more branches locally you'll need to keep track of what branch you've made changes to locked files, as the system will not prevent you from modifying the same locked file on multiple different branches!
develop
branch, but there is an up-stream change on origin/develop
for FirstPersonProjectileMaterial
, indicated with the yellow exclamation mark.promoted
branch, indicated with the red exclamation mark. (NOTE: The plugin does not currently report the branch name the changes are on.)Generally speaking, the field next to Uses Git LFS 2 File Locking workflow
should match your Git server's User Name
, like so:
(If you find that the checkmark turns blue shortly after checking out a file, then the LFS name is incorrect, update it to the name it says checked out the file)
You can lock individual files or you can hold shift
to select and lock multiple at once, which can be quite a bit faster than locking them individually.
You can unlock individual files or you can hold shift
to select and unlock multiple at once, which can be quite a bit faster than unlocking them individually.
You can lock every file in a folder by right clicking on the folder and clicking Check Out
.
View the owner of a file lock simply by hovering over the asset icon. Your locked files have a red check-mark, other user's locks will show up with a blue checkmark.
You can pull the latest changes from your currently checked-out branch within the editor. This doesn't always work smoothly, but effort has been made to improve this process. It is still recommended to always save changes before doing this, however.
Submit to revision control
will create a local commit, push it, and release your file lock.
(While you cannot check out branches within the plugin, it is fully branch-aware! In this scenario, the user has checked out the develop
branch, so their change is pushed to origin/develop
.)
You can learn more about how we set up our Git repository at the PBCore wiki.