Setting up Repos

After you install Git Fusion, you must configure your repos.

This chapter discusses the following topics:

How does Git Fusion map Perforce depots to Git repos?

To populate a repo hosted by Git Fusion, a Perforce administrator creates a configuration file (p4gf_config) that identifies the scope of Perforce depot data contained in the repo, along with character encoding and branching directions. The map of the Perforce depot location to the Git repo uses the same syntax as standard workspace (client) views, and is referred to in this guide as the view or repo view. In the following repo view, the path to the left represents a Perforce depot location, and the path to the right represents the Git repo work tree:

//depot/main/your_project/foo/... foo/...

In this case, the contents of Perforce depot directory //depot/main/your_project/foo/maps to the foo/ directory in the Git repo.

You can also represent the top level of the Git repo work tree with an ellipsis:

//depot/main/your_project/foo/... ...

Repo configuration files enable you to define multiple branch mappings. Git users can push commits that have linear history or merged history, including two-parent merges and octopus (3+ parent-) merges.

Git Fusion uses two types of repo configuration files:

  • The global configuration file, which is generated automatically and stored in the top level of the //.git-fusion depot in Perforce.

    You edit this file to provide global defaults, specifically character set preferences, branch enablement, pre-flight commit scripts to enforce local policy, and author permissions requirements.

  • Repo-specific configuration files, which the administrator creates from templates provided in the OVA or distribution package, and which are stored in repo-specific directories in the //.git-fusion depot in Perforce.

    Any preferences that you do not specify in a repo-specific configuration file default to those in the global configuration file.

Note

You can choose not to create a repo configuration file, and instead map your repo to Peforce depot locations by creating a Perforce workspace specification and letting Git Fusion create the configuration file.

For more information, see Configuring repos.

Configuring global defaults for repos

The User and Client Initialization script (p4gf_init.py) creates the global configuration file and stores it in Perforce at //.git-fusion/p4gf_config. You can edit any of its key values that you want repo configuration files to inherit by default.

Note

You can run this script any time after Git Fusion has been initialized in your Perforce service with the Super User Initialization script (p4gf_super_init.py). If p4gf_init.py has not been run, p4gf_init_repo.py will invoke it automatically. If neither has been run, the first push or clone against this Git Fusion server will invoke them both automatically.

View the file header comments or see the table below for details.

Table 2. Global configuration file: keys and default values

Section Headers or Keys Definition Default Value Valid Values
[repo-creation] Section header for settings that control how Git Fusion creates new repos. NA Enter the section header exactly as shown.
charset Defines the default Unicode setting that Git Fusion applies to new repos. This setting is valid only when Git Fusion interacts with a Unicode-enabled Perforce server. charset: UTF-8 Any P4CHARSET value; run p4 help charset for a list of valid values.
depot-path-repo-creation-enable

Allow Git users to create new repos by pushing/pulling a git url which specifies a Perforce depot path. This is similar to creating a repo from a p4 client.

no

Yes equivalent (Yes, On, 1, True) or No equivalent (No, Off, 0, False).

No: Automatic repo creation from a depot path is disallowed.

Yes: Automatic repo creation from a depot path is allowed. Under the following conditions a new repo will be created:

  • The repo name is formated as: depotname/reponame/branchname

  • depotname is a defined Perforce depot of type='local'

  • No p4gf_config nor p4 client exists with the translated name: depotname_0xS_reponame_0xS_branchname

If the conditions are not met, the push/pull will fail with the expected error message reporting the repo is not defined.

The newly created repo p4gf_config will contain:

[@repo] description = Created from 'depotname_0xS_reponame_0xS_branchname'

[Hzb5rdffTRGEsjotvTLoHg==]
git-branch-name = master
view = //depotname/reponame/branchname/... ... 

For a clone/pull situation, any files under //depotname/repo/branch will be imported into a new Git repo's master branch.

For a push situation, any files in the pushed Git branch will be imported into a new Perforce depot path.

depot-path-repo-creation-p4group

Restrict which authenticated Git pushers are allowed to create new repos when depot-path-repo-creation-enable is enabled.

Unset/None

Unset/None: No restriction: all Git pushers can create new repos from depot paths if depot-path-repo-creation-enable is enabled.

Set this to the name of an existing Perforce p4 group to restrict this feature to members of that group.

You can also use p4 protect to grant/deny write permission to areas of the Perforce depot.

[git-to-perforce] Section header for settings that define how Git commits are converted to Perforce changes (submits). NA Enter the section header exactly as shown.
change-owner Defines whether Git Fusion assigns either the Git commit author or the Git pusher as the owner of a pushed change (submit). author Either author or pusher.
enable-git-branch-creation Defines whether Git Fusion creates a new branch of Perforce depot file hierarchy for each copied branch of Git workspace history, including Git task branches as Git Fusion anonymous branches. See Git branch and merge: effect of configuration key values for more information about setting this key. Yes

Yes equivalent (Yes, On, 1, True) or No equivalent (No, Off, 0, False). When set to No, Git Fusion prohibits the copy of any new Git branches to Perforce that are not defined in the repo’s configuration file, and also translates Perforce file hierarchy merges to Git as file edits, not as Git merge commits. However, Git Fusion will still copy Git merge commits between Perforce branches that are defined in the repo's configuration file.

To permit Git Fusion to create new branches for Swarm reviews, you must also enable enable-swarm-reviews.

enable-swarm-reviews Permits branch creation for Swarm reviews, even when enable-git-branch-creation is disabled. See Using Swarm for code review for more information about Swarm reviews. Yes

Yes equivalent (Yes, On, 1, True) or No equivalent (No, Off, 0, False). Yes enables Git Fusion to create a new branch of Perforce depot file hierarchy for each new Swarm review and permits merge commits in the review history, which become anonymous branches in Perforce.

This setting overrides enable-git-branch-creation and enable-git-merge-commits for Swarm reviews.

No disables the creation of branches for Swarm reviews, effectively disabling the ability to push Swarm reviews from Git.

enable-git-merge-commits Defines whether Git Fusion copies merge commits and displays them in Perforce as integrations between Perforce branches. See Git branch and merge: effect of configuration key values for more information about setting this key. Yes

Yes equivalent (Yes, On, 1, True) or No equivalent (No, Off, 0, False). No means that Git Fusion rejects all merge commits; integrations and merges between Perforce branches must be performed using Perforce.

enable-git-submodules Defines whether Git Fusion allows Git submodules to be pushed to Perforce. Yes Yes equivalent (Yes, On, 1, True) or No equivalent (No, Off, 0, False). No prevents Git submodules from being introduced into Git Fusion. If any submodules have already been pushed to Git Fusion, they will be left intact and be reproduced through clone/pull.
ignore-author-permissions Defines whether Git Fusion evaluates both the author's and pusher's Perforce write permissions during a push or evaluates only the pusher's permissions. No Yes equivalent (Yes, On, 1, True) or No equivalent (No, Off, 0, False). When set to yes, Git Fusion evaluates only the pusher’s permissions.
preflight-commit Enables you to trigger pre-flight commit scripts that enforce local policy for Git pushes. This can be especially useful if you have Perforce submit triggers that could reject a push and damage the repository. For more information about setting this key, see Adding preflight commits to reject pushes. none

Pass passes all pushes that Git Fusion would otherwise permit, and Fail rejects all pushes; these values are primarily intended for temporarily disabling a preflight commit. You can add a path to a message as an argument to either of these values.

To enable a preflight commit script, use the syntax command argument, where command is the path to the script. Arguments can include Git Fusion and Perforce trigger variables, as in the following example:

preflight-commit = /home/git/myscript.sh %repo% %sha1%

read-permission-check Enables you to require that Git clone, pull, or fetch requests check the Perforce protections table for the puller's read permission on the files being pulled. group Group bypasses a Perforce permissions check on pull transactions, relying on membership in a Git Fusion pull permission group for access to the files. User enables a check that the puller's Perforce user has Perforce read permission for all files within the repo. For more information, see Enforce Perforce read permissions on Git pull
git-merge-avoidance-after-change-num If the Perforce service includes any changelists submitted by Git Fusion 13.2 or earlier, you can prevent unnecessary merge commits by setting this key to the number of the last changelist submitted before your site upgraded to a later version of Git Fusion. p4 counter change

Keep the default value, p4 counter change, if you have no commits from earlier instances of Git Fusion (13.2 or earlier). At the first initialization of a Git Fusion repo, Git Fusion writes the changelist number to the global configuration file.

If you do have commits from Git Fusion 13.2 or earlier, provide the number of the the last changelist submitted before your site upgraded to a later version of Git Fusion.

job-lookup

Set the format for entering Perforce jobs in Git commit descriptions so that they are recognized by Git Fusion and appear in Perforce changelists as fixes. By default, job IDs whose string starts with "job" (as in job123456) are passed through to the changelist description and job field. Use this option if you want Git Fusion to recognize additional expressions, such as JIRA issue IDs.

For more information about including jobs in Git commit descriptions, see Referencing Perforce jobs in a commit.

none

Enter an expression that Git Fusion will pass to p4 jobs -e to look for matching jobs. You can add multiple fields, one per line.

For example, let's say your job specification includes the field DTG_DTISSUE for JIRA issue IDs. If you set job-lookup: DTG_DTISSUE={jobval}, then Git Fusion runs p4 jobs -e DTG_DTISSUE=XY-1234 when it sees a Git commit message that includes Jobs: XY-1234.

You do not need to add a value for standard Job IDs, stored in the job spec's Job field, whose string starts with "job" (as in job123456). These are passed through by default.

For more information about the p4 jobs command and the expressions that you can pass using -e, see the Perforce Command Reference.

depot-branch-creation-enable

Allow Git users to create new fully-populated depot branches within Perforce.

For more information, see Enabling Git users to create fully-populated branches

no

no: Any new branches pushed by Git users go into //.git-fusion/branches/ as lightweight depot branches.

explicit: Push to special remote branch reference depot-branch/branch_name. This creates a new fully-populated depot branch in Perforce. For example, git push origin mybranch:depot-branch/research creates a new Perforce depot branch under //depot/myrepo/research/.

all: Each new Git branch pushed by Git users goes into a new fully-populated depot branch in Perforce. For example, git push origin mybranch:research creates a new Perforce depot branch under //depot/myrepo/research/.

depot-branch-creation-p4group

Restrict the authenticated Git pushers who are allowed to create new fully-populated depot branches, if depot-branch-creation-enable is enabled.

For more information, see Enabling Git users to create fully-populated branches

None

Set to the name of an existing Perforce p4 group to restrict this feature to members of that group.

Unset/None: No restriction. All Git pushers can create new fully-populated depot branches if depot-branch-creation-enable is enabled. You can unset this property and use the p4 protect command to fine-tune Perforce user and group access to specific areas of the Perforce depot.

depot-branch-creation-depot-path

Tell Git Fusion where to create new fully-populated depot branches, if depot-branch-creation-enable is enabled.

Default path is //depot/{repo}/{git_branch_name}

For more information, see Enabling Git users to create fully-populated branches

(at left)

Use the following string substitutions to set the location of new branches:

{repo}: returns the name of the Git Fusion repo receiving this push.

{git_branch_name} : returns the name of the pushed branch reference, such as, for example, myfeature in the command git push master:depot-branch/myfeature. Perforce path rules apply: @, #, %, * , //, ... are prohibited; / is permitted. This substitution must be included somewhere in the string, or it becomes impossible for Git users to create more than one branch to a single repo.

{user}: returns the Perforce user ID of the pusher.

depot-branch-creation-view

Set how the depot-path set in depot-branch-creation-depot-pathshould appear in Git.

For more information, see Enabling Git users to create fully-populated branches

... ...

Enter a Perforce view specification that maps Perforce depot paths (left side) to Git work tree paths (right side). Perforce depot paths are relative to the root set in depot-branch-creation-depot-path.

The default "... ..." maps every file under the depot-branch-creation-depot-path root to Git. Right side paths must match the right side for every other branch already defined within a repo.

enable-git-find-copies

When Git reports a copy file action, store that action in Perforce as a p4 integ. Often set in tandem with enable-git-find-renames.

For more information, see Detecting Git copy/rename and translating to Perforce

No

No/Off/0%: Do not use Git's copy detection. Treat all possible file copy actions as p4 add actions.

1%-100%: Use Git's copy detection. Value passed to git diff-tree --find-copies=n.

Git Fusion also adds --find-copies-harder whenever adding --find-copies.

enable-git-find-renames

When Git reports a rename (also called move) file action, store that in Perforce as a p4 move. Often set in tandem with enable-git-find-copies.

For more information, see Detecting Git copy/rename and translating to Perforce

No

No/Off/0%: Do not use Git's rename detection. Treat all possible file rename actions as independent p4 delete and p4 add actions.

1%-100%: Use Git's rename detection. Value passed to git diff-tree --find-renames=n.

[perforce-to-git] Section header for settings that define how Perforce changes (submits) are converted to Git commits. NA Enter the section header exactly as shown.
enable-stream-imports

Enables you to convert Perforce stream import paths to Git submodules when you clone a Git Fusion repository. If set to Yes, you must also set either http-url or ssh-url.

For more information, see Enabling stream import paths as Git submodules.

No Set to Yes equivalent (Yes, On, 1, True) to enable Git Fusion to convert compatible stream import paths to Git submodules. Set to No equivalent (No, Off, 0, False) to have import paths and their history incorporated in the Git repo for the stream.
http-url

The URL used by Git to clone a repository from Git Fusion over HTTP. This property is required if you want to use Perforce stream import paths as git submodules and you use HTTP(S).

none

You can enter the full host and repo name that you use to clone a repo from Git Fusion, or you can include variable placeholders that will be replaced by values from the Git Fusion environment:

{host}: returns the fully qualified hostname of the Git Fusion host computer, as fetched by the Linux function gethostname(). If this does not resolve to a value that is recognized by the client (a hostname that can be used to perform Git commands against the Git Fusion repos), then use the actual, full hostname rather than the variable.

{repo}: returns the name of the Git Fusion repository.

Example with only variable placeholders: http://{host}/{repo}

Example with hostname provided: http://p4gf.company.com/{repo}

For HTTPS installations, use the https:// prefix.

ssh-url The "URL" used by Git to clone a repository from Git Fusion using SSH. This property is required if you want to use Perforce stream import paths as git submodules and you use SSH. none

You can use the following variable placeholders that will be replaced by values from the Git Fusion environment:

{user}: returns the SSH user performing the Git clone. If a user name is not found, this value defaults to git.

{host}: returns the fully qualified hostname of the Git Fusion host computer, as fetched by the Linux function gethostname(). If this does not resolve to a value that is recognized by the client (a hostname that can be used to perform Git commands against the Git Fusion repos), then use the actual, full hostname rather than the variable.

{repo}: returns the name of the Git Fusion repository.

Example with only variable placeholders: {user}@{host}:{repo}

Example with hostname provided: {user}@p4gf.company.com:{repo}

[authentication] Section header for settings that define authentication options. NA Enter the section header exactly as shown.
email-case-sensitivity Defines whether Git Fusion pays attention to case when matching Git user email addresses to Perforce user account email addresses during the authorization check. For more information about how Git Fusion uses email addresses to authorize users, see Mapping Git users to Perforce accounts. no

Yes equivalent (Yes, On, 1, True) or No equivalent (No, Off, 0, False). Yes enforces email address case sensitivity.

author-source Defines the source that Git Fusion uses to identify the Perforce user associated with a Git push. For more information about how Git Fusion associates Git authors with Perforce users, see Mapping Git users to Perforce accounts. git-email

Use any one of the following values:

  • git-email: Use the email address of the Git author to look for a Perforce user account with the same email address. Git Fusion consults the p4gf_usermap file first, and if that fails to produce a match, it scans the Perforce user table.

  • git-user: Use the user.name field in the Git commit. This is the part of the author field before the email address.

  • git-email-account: Use the account portion of the Git author's email address. If the Git author's email value is <[email protected]_shire.com>, Git Fusion uses the Perforce account samwise.

You can also tell Git Fusion to iterate through multiple source types until it finds a matching Perforce account. Specify the source types in order of precedence, separated by commas. For example: git-user, git-email-account, git-email.

[quota] Section header for settings that define push limit options. NA

Enter the section header exactly as shown.

limit_space_mb

Natural number representing the number of megabytes of disk space that can be consumed by any single repo. This value does not include the spaced consumed on the Perforce server.

0

If the value is zero or less, the limit is not enforced.

limit_commits_received

Natural number representing the maximum number of commits allowed in a single push.

0

If the value is zero or less, the limit is not enforced.

limit_files_received

Natural number representing the maximum number of files allowed in a single push.

0

If the value is zero or less, the limit is not enforced.

limit_megabytes_received

Natural number representing the maximum number of megabytes allowed in a single push.

0

If the value is zero or less, the limit is not enforced.

The table below shows how the values you select for the enable-git-branch-creation and enable-git-merge-commits keys affect Git users' ability to perform branches and merges. Inform your Git users if you implement Scenarios 2, 3, or 4, because these scenarios will restrict their normal use of Git's branch and merge functionality.

Table 3. Git branch and merge: effect of configuration key values

Scenario enable-git-branch-creation Value enable-git-merge-commits Value Result
1 Yes Yes This scenario has the least impact on Git users' usual workflow. Any Git user with a corresponding valid Perforce user (either his or her own user or unknown_git) can create and push branches and merge commits as they normally do in Git.
2 No No This is the most restrictive scenario for Git users. They cannot push any new Git branches that are not expressly defined in a repo's configuration file, and also must ensure that they push commits that have a linear history.
3 Yes No This scenario has a moderate impact on Git users. They can push new Git branches to Perforce but they must ensure that all commits have a linear history. If they attempt to push a merge commit, Git Fusion displays the error message: remote: Merge commits are not enabled for this repo. Only Perforce users can perform merge and integration work using a Perforce workspace.
4 No Yes This scenario has a moderate impact on Git users. They can push merge commits between Perforce branches that are defined in a repo's configuration file, but cannot push new Git branches to Perforce. If they attempt to push a new Git branch, Git Fusion displays the error message: remote: Git branch creation is prohibited for this repo.

Configuring repos

To specify the parts of a Perforce depot that are accessible to a Git Fusion repo, you can use any of the following:

  • Configure repos with a repo configuration file (p4gf_config)

    Repo configuration files let you define an unlimited number of branches, and repo-specific options including Unicode character sets.

  • Configure repos from a Perforce workspace

    This approach can be convenient if you already have workspace definitions that you want to use as Git repos. You use an existing a workspace or create a new one, and Git Fusion generates the repo configuration file using the workspace view. The global configuration file file provides the default options such as branching preferences and charset definitions. This approach does not allow you to define branches when the configuration file is first created, but you can edit the file later to set repo-specific options and add branch definitions (within certain limitations).

  • Use a Perforce depot path in a Git remote URL

    If enabled, this approach lets some or all Git users define repo configurations by simply supplying a Perforce depot path as part of the remote URL to git clone, pull, or push commands. Git Fusion will generate the repo configuration file using the path supplied. The global configuration file file provides the default options such as branching preferences and charset definitions. This approach does not allow you to define branches when the configuration file is first created, but you can edit the file later to set repo-specific options and add branch definitions (within certain limitations).

Important

Git Fusion does not automatically handle changes to repo definitions throughout the system. Once a repo has been cloned from Git Fusion, only limited modifications should be made to the repo configuration file. For more information about how to modify repos safely, see Modifying repo configuration files safely.

Configure repos with a repo configuration file (p4gf_config)

  1. Copy the repo configuration file template, p4gf_config.repo.txt, to create a new config file.

    If you installed Git Fusion using the OVA or operating system specific packages, the template is in the /opt/perforce/git-fusion/libexec directory. If you installed using the distribution tarball, the location is the directory where you elected to install Git Fusion.

  2. Enter the key values and Perforce-to-Git mapping (view) for your repo.

    Ensure that the Git work tree path notation on the view field's right side matches for all branches.

    Note

    Views can include overlay and exclusionary mappings, but note that the Git Fusion submit triggers (which enable atomic pushes) ignore exclusionary mappings, because the scope of submit triggers is limited to areas that are potentially of interest to Git Fusion. Exclusionary mappings are ignored for the calculation of areas of interest, because one repo's exclusions could conflict with another's inclusion.

    Note

    If in a given repo configuration, there is Perforce path that is mapped to two or more Git branches, then that path is a "shared" path and thus read-only from the Git perspective.

    For detailed information about the repo configuration keys and view syntax, see the repo configuration file’s detailed header comments and Repo configuration file: key definitions and samples.

  3. Submit the repo configuration file to Perforce.

    Save the file as p4gf_config.

    Submit the file to //.git-fusion/repos/repo_name/p4gf_config

    The repo_name can include the forward slash (/) and colon (:) characters, but these characters must be encoded as _0xS_ and _0xC_

    Note

    For example: repo name foo/bar:zee is created by submitting the following p4gf_config

    //.git-fusion/repos/foo_0xS_bar_0xC_zee/p4gf_config

  4. Initialize (populate) the repo.

    See Initializing repos on the Git Fusion server

Repo configuration file: key definitions and samples

A repo-specific configuration file can include (and override) any property included in the global configuration file, in addition to the following.

Table 4. Repo-specific configuration files: keys and default values

Section Headers or Keys Definition Default Value Valid Values
[@repo] Section header for the repo configuration file. You can override any global configuration property by adding it to this section. NA Enter the section header exactly as shown.
description Repo description returned by the @list command NA Enter a concise repo description.
[git-fusion-branch-id] Section header to define a unique Git Fusion branch. NA Each branch must have a unique ID in the form of an alphanumeric string. Do not edit this value after you clone the repo.
git-branch-name Defines a name specified in a local repo for a Git branch. NA A valid Git branch name. Do not edit this value after you clone the repo.
view Defines a Perforce workspace view mapping that maps Perforce depot paths (left side) to Git work tree paths (right side). NA Correctly formed mapping syntax; must not include any Perforce stream or spec depots, and all depot paths on the right side must match exactly across all branch definitions. You can add and remove only certain types of Perforce branches from this view after you clone the repo. See Modifying repo configuration files safely
stream Defines a Perforce stream that maps to the Git branch. NA Provide a stream name using the syntax //streamdepot/mystream. A Git Fusion branch can be defined as a view or a stream but not both. If your branch is defined as stream, it can include only one stream. For more information, see Working with Perforce streams.
read-only Prohibit git pushes that introduce commits to the branch. No

Yes equivalent (Yes, On, 1, True) or No equivalent (No, Off, 0, False). Yes makes the branch read-only and prevents users from committing changes.

Sample repo configuration files

Here are two examples of repo configuration files:

Important

The Git work tree path notation on the view field's right side must match exactly for all branches defined in a repo configuration file to enable merge commits. Otherwise, Git Fusion will fail during a merge between the branches and report the error file(s) not in client view.

Example 1:
[@repo]
description = A repo configuration file that maps two branches, master and release, into the top level of the Git repo.

[master]
git-branch-name = master
view = //depot/main/your_project/... ...


[release]
git-branch-name = release
view = //depot/release/your_project/... ...
Example 2:
[@repo]
description = A repo configuration file that maps portions of two branches, master and release, into subdirectories in the Git repo
charset = utf8

[master]
git-branch-name = master
view = //depot/main/your_project/foo1/... foo1/...
       //depot/main/your_project/bar1/... bar1/...

[release]
git-branch-name = release
view = //depot/release/your_project/foo1/... foo1/...
       //depot/release/your_project/bar1/... bar1/...

Configure repos from a Perforce workspace

You can use a Perforce workspace (client) to map a single fully-populated Perforce branch to a Git Fusion repo and let Git Fusion generate the repo configuration file for you. The global configuration file file provides the default options such as branching preferences and charset definitions. This approach does not allow you to define branches when the configuration file is first created, but if your global default is to enable branching, you can edit the file later to add branch definitions. For more information, see Modifying repo configuration files safely.

This approach can be convenient if you already have workspace definitions that you want to use as Git repos.

  1. Create a Perforce workspace.

    The workspace name becomes the repo name.

    Note that the Client name can include the forward slash (/) and colon (:) characters. However slash (/) must be encoded as _0xS_. The resulting internal Git Fusion repo name will also encode the colon (:) as _0xC_. The public git repo name will retain any slash (/) and colon (:) characters.

    Note

    For example: Client foo_0xS_bar:zee will result in the internal repo p4gf_config //.git-fusion/repos/foo_0xS_bar_0xC_zee/p4gf_config.

    The public git url will use the repo name foo/bar:zee.

    Use the View field to define a single branch mapping. The mappings determine what portions of the Perforce depot are translated into Git repo branches and vice versa.

    You can create simple and complex mappings that have the following:

    • Exclusionary and overlay mappings.

    • Different permissions for each depot path; for example, one depot path that includes files with read and write permissions, and another depot path that includes files with only read permissions.

    The example below shows a workspace view with the key fields defined: Client, Owner, Root, and View. Note that only the Client and View fields are meaningful to Git Fusion.

    Client: project_repo
    Owner: p4bob
    Root: /home/bob
    
    # View that maps into the top level of the Git repo
    View:
       //depot/main/your_project/... //project_repo/...
    
    # View that maps into a sub directory in the Git repo
    View:
       //depot/main/your_project/foo1/... //project_repo/foo1/...
    
  2. Save the workspace.

  3. Initialize (populate) the repo using either of these methods:

    • If you issue a Git command like git clone using the Perforce workspace name for the repo name, Git Fusion will automatically initialize the new repo, and then pass it off to Git for transfer to the Git client.

      $ git clone https://gfserver/Jam
      Cloning into 'Jam'...
      Perforce: Copying files: 84
      Perforce: 100% (23/23) Copying changelists...
      Perforce: Submitting new Git commit objects to Perforce: 24
      remote: Counting objects: 125, done.
      remote: Compressing objects: 100% (69/69), done.
      remote: Total 125 (delta 51), reused 89 (delta 33)
      Receiving objects: 100% (125/125), 174.80 KiB, done.
      Resolving deltas: 100% (51/51), done.
      $ cd Jam

Git Fusion uses the workspace view only once, using defaults from the global configuration file, to create a p4gf_config file for the repo that it automatically stores in //.git-fusion/repos/repo_name/p4gf_config. Because Git Fusion only uses the workspace view once to generate a p4gf_config file, you can delete it from the Perforce depot after repo initialization.

For more information about how to define Perforce workspace views, see the P4 User's Guide, "Configuring P4."

To delete invalid or outdated repo views, see p4gf_delete_repo.py.

Use a Perforce depot path in a Git remote URL

If enabled, this approach lets some or all Git users define repo configurations by simply supplying a Perforce depot path as part of the remote URL to git clone, pull, or push commands. Git repos can be created from existing Perforce depot paths, and Perforce depot paths can be populated from existing Git repos.

  • You can instruct Git Fusion to create a new Git repo simply by running git clone, or git pull with a URL that matches an existing Perforce depot path. For example, if your Perforce depot is organized with the main branch of the Jam project in //depot/Jam/MAIN, then you can quickly create a Git repo for that branch of the project by supplying the depot path to git clone:

    $ git clone https://gfserver/depot/Jam/MAIN
    Cloning into 'MAIN'...
    remote: Counting objects: 2070, done.
    remote: Compressing objects: 100% (1379/1379), done.
    remote: Total 2070 (delta 1218), reused 1074 (delta 325)
    Receiving objects: 100% (2070/2070), 600.52 KiB, done.
    Resolving deltas: 100% (1218/1218), done.
    $
    $ cd MAIN
    $ git branch
    * master
    $ ls
    src
    $
    $ p4 dirs //depot/Jam/MAIN
    //depot/Jam/MAIN/src

  • The depot path supplied will be automatically mapped to Git branch master, with all files and history for that path immediately available in the new repo.

  • You can also push an existing Git repo's branch to a particular Perforce depot path:

    $ cd myrepo
    $ git push https://gfserver/depot/myproject/main master
    $
    $ p4 dirs //depot/*/*
    //depot/myproject/main

  • Git Fusion uses the supplied Perforce depot path, along with defaults from the global configuration file, to create a p4gf_config file for the repo that it automatically stores in:

    //.git-fusion/repos/depotname_0xS_reponame_0xS_branchname/p4gf_config.

  • While the above examples use HTTPS, SSH URLs are also supported.

  • This functionality must be enabled with the Git Fusion configuration option, depot-path-repo-creation-enable.

  • You can restrict this functionality to a specific group of Perforce users by setting depot-path-repo-creation-p4group equal to a Perforce group name.

  • Stream depots are not supported.

  • Like most options, these can be set in either the global or repo config file. For detailed usage of the above configuration options, see Table 2, “Global configuration file: keys and default values”.

Initializing repos on the Git Fusion server

Once you have created a repo configuration file or workspace that maps Perforce depot locations to your repo, you or your Git users can perform the initial clone that populates the Git Fusion server:

  • If you, the administrator, perform the initial clone, you can absorb the time cost of initializing large repos and fix any repo configuration issues.

    The time the initial clone takes to complete depends on many factors, like the amount of Perforce data Git Fusion must translate into Git data and the amount of network traffic. For large depots, the initial clone can take several hours.

  • If you choose to let your Git users initialize new repos, simply distribute the Git repo URLs to your users; the first git clone transaction will populate the repo on the Git Fusion server.

For administrators, the Repo Initialization script (p4gf_init_repo.py) provides a convenient means of initializing new repos.

p4gf_init_repo.py --start n repo_name

Use --start n to copy history as of a particular changelist. The repo_name can be either the subdirectory name in //.git-fusion/repos/repo_name/p4gf_config or the name of a workspace.

The example below initializes a repo named "winston" with history starting at changelist 144656:

$ p4gf_init_repo.py --start 144656 winston

For information about additional options available when you run this script, see the Script Command Reference.

Importing existing Git repos into Git Fusion

There are three approaches to importing existing Git repos into Git Fusion. All result in Git branches being available to Perforce users.

Two approaches can generally be executed by end users without administrative intervention (beyond initial configuration). These methods offer simplified steps when only a single branch needs to be imported.

A third approach generally requires an administrator, but offers the most configuration options.

Creating a repo configuration file for import of existing repo

The following example is a repo configuration file with a view mapping that defines a repo that does not currently exist in Perforce. It should be submitted to //.git-fusion/repos/git_project/p4gf_config. Based on this path, the Git Fusion repo will be named git_project. When the Git user pushes their project's master branch to this Git Fusion repo for the first time, Git Fusion will populate the Perforce depot at //depot/vperry/git_project/. When the Git user pushes other branches, Git Fusion will store changes on lightweight branches, under //.git-fusion/branches/.

Additional notes about creating such repo configuration files:

  • The right-side view mapping should contain only a workspace root or an ellipsis (…). Do not specify any subdirectories. Git Fusion will create the appropriate subdirectories in the Perforce depot upon initialization.

  • If the existing Git repo contains multiple branches, you have the option to map each one to a Perforce depot path, although it is not required.

    Assuming that you have configured your repo configuration file to allow for pushing branches, any unmapped branches that are pushed to Git Fusion will automatically be stored on lightweight branches, under //.git-fusion/branches/. At least one branch (for example, master) should be mapped to a Perforce depot path.

[@repo]
description = Git Fusion repo created from git_project
charset = utf8
enable-git-branch-creation = yes
ignore-author-permissions = no

[master]
git-branch-name = master
view = //depot/vperry/git_project/... ...

For more information about configuring repos, see Configuring repos.

Importing an existing repo using a Perforce workspace or repo configuration file

  1. Push the original existing Git repo to Git Fusion.

    1. Clone the existing repo and cd into the resulting local repo directory.

    2. Retain a link to the upstream repo to enable updates.

      git remote rename origin upstream

    3. Ensure that you check out all branches of the repo locally.

      git checkout -b branch upstream/branch

    4. Establish remote tracking between the local repo and Git Fusion.

      Note

      For the repo_name, subtitute either a workspace name if using a Perforce workspace, or the p4gf_config parent folder name if you defined a new repo configuration file (git_project in the example above).

      git remote add origin https://Git_Fusion_Server/repo_name

      Note

      For really huge repos avoid an HTML timeout by configuring the remote origin using the SSH protocol.

      git remote add origin unixacct@Git_Fusion_Server:repo_name

      For more information about SSH authentication , see Authenticating Git Users using SSH.

    5. Push the local repo's branches to Git Fusion individually, or all at once as in the command below.

      git push -u --all origin

  2. Verify the imported data.

    1. Log in to the Git Fusion server and remove the repo_name directory from the P4GF_HOME/views directory (if you installed using the configure-git-fusion.sh script and accepted all defaults, this would be ~git/.git-fusion/views/repo_name).

      This step forces Git Fusion to rebuild the Git repo from data stored in Perforce, and is only necessary during this verification.

    2. Clone the repo back from Git Fusion.

      Be sure to save the repo in a different directory with a different name than the original local repo.

      git clone unixacct@Git_Fusion_Server:repo_name newdir

    3. Run git log --stat > log.new in the clone you created in the previous step.

    4. Run git log --stat > log.orig in your original local repo.

    5. Compare the two logs for any data differences.

      If the logs do not match, email the data to Perforce Support () for assistance.

Modifying repo configuration files safely

Once a Git repo has been cloned, any changes to that repo configuration can invalidate its history in ways that prevent an identical rebuild of the Git repo after deleting it.

The following changes, however, are safe:

  • Add a Perforce branch that has no impact on Git history; that is, a Perforce branch that does not merge into a Perforce branch already mapped to a Git branch.

    You can add a Perforce branch that merges into a Perforce branch that is already mapped to a Git branch, as long as you do not delete the Git repo and try to recreate it.

    The history reflected in the Git repo will not match what is in Perforce: any merges into the pre-existing branch will have been recorded as edits. That said, the content in the Git repo will match what is in Perforce, and Git Fusion will record any future merge actions correctly. If you delete the Git repo (using p4gf_delete_repo.py) and then recreate it using the repo configuration, then these edit commits will become merge commits and result in a new Git repo that is not compatible with the previous version.

    Example

    Let's say you have //depot/main and //depot/dev. There is history between the two, with changes originating in //depot/dev and merges into //depot/main. If you map //depot/main to master and initialize a new Git Fusion repo, then the merges from //depot/dev to //depot/main are recorded as edits in Git history. If you go on to add a new mapping for //depot/dev, you will get Git history for //depot/dev but it will not change those edit commits in any way. If you delete and recreate this Git repo, it will be incompatible with the original generated Git repo, because the edit commits will be regenerated as merge commits.

  • Remove a Perforce branch that touches no other Git history; that is, a Perforce branch that never merges into another surviving branch.

    A Perforce branch that merges into any surviving branch is a parent to Git merge commits. Removing it would break history: a rebuild of history would convert merges into edits.

    Note that a push from a clone of this repo that contains additional commits on the deleted branch would recreate the Perforce branch as a lightweight branch.

Any other edits to a repo configuration file -- including changes to branch mappings -- require that you create a new repo configuration, distribute the new repo to the affected users, and delete the original. Ensure that all affected Git users push any pending commits to the original repo before you create its replacement.

Important

Whenever you remove a branch from a repo configuration file, you should also run p4gf_submit_trigger.py --rebuild-all-gf myperforceserver:port [super].

Converting a lightweight branch into a fully-populated branch

When you push a new Git branch that is not mapped to a Perforce branch in a repo configuration file, that new branch is submitted to Perforce as a lightweight branch, under //.git-fusion/branches/. For efficiency, such branches only contain the minimal set of integrations and changes required to represent the pushed history. These branches are transparent to Git users, but their sparse nature may hinder collaboration with Perforce users.

A Git branch that is mapped to a Perforce branch in a repo configuration file will be fully-populated at the depot path specified. Again, the choice of branch treatment is transparent to Git users. When Git users and Perforce users need to share a persistent branch, it is ususally best to use a fully-populated branch. This can be accomplished in one of two ways:

  • Use Git to merge changes from an unmapped branch (lightweight in Perforce) to a mapped branch (fully-populated in Perforce), and push.

  • Convert a lightweight branch to a fully-populated branch, using the steps below.

  1. Add the new, as-yet unpopulated target branch to the repo's p4gf_config file.

    [my_new_branch]
    git-branch-name : my_new_branch
    view : //depot/my_project/my_new_branch/... ...

  2. In Git, create the new branch, pointing to the branch reference where you want to start commit history.

    $ git branch my_new_branch <branch ref or commit sha1>

  3. Push the new branch through Git Fusion to Perforce.

    $ git push origin my_new_branch

The branch is now fully populated in Perforce, and both Perforce and Git users can work in it.

Enabling Git users to create fully-populated branches

As discussed in Converting a lightweight branch into a fully-populated branch, fully-populated Perforce branches are the best choice when Git and Perforce users need to collaborate on the same branch.

An administrator or user with access may add a new branch mapping to the repo-specific p4gf_config file, so that when a Git user pushes to the new branch, it is fully-populated in Perforce. For more information on adding new branches, see Modifying repo configuration files safely

The two approaches below let Git users push fully-populated branches without administrative intervention (apart from initial configuration).

Create a fully-populated branch only when a Git user explictly chooses to do so

You can enable Git users to push some branches as fully-populated branches, for sharing with Perforce users, while letting others be pushed as lightweight branches:

  1. Enable depot branch creation in the global or repo-specific p4gf_config file with the explicit value.

    Use the global configuration file to enable this option for all repos:

    [git-to-perforce]
    depot-branch-creation-enable = explicit

    Alternatively, use a repo-specific configuration file to enable it repo-by-repo:

    [@repo]
    depot-branch-creation-enable = explicit

    For additional configuration options, see the depot-branch-creation-* keys in Table 2, “Global configuration file: keys and default values”

  2. In Git, create a new branch.

    $ git checkout -b new_git_branch

  3. Explicitly push the new branch using the following syntax to create and map a fully-populated branch in Perforce:

    $ git push origin new_git_branch:depot-branch/new_p4_branch

    This creates a new fully-populated branch in the Perforce depot and maps it to the Git branch, new_git_branch:

    //depot/my_project/new_p4_branch/...

    In the command above, depot-branch is a keyword which instructs Git Fusion to create a new fully populated branch and map it to the Git branch being pushed. Similar to pushing a Swarm review, the remote branch reference depot-branch/new_p4_branch is never created on the remote Git Fusion server. Instead, a new remote reference is created for new_git_branch. After using this method, it is necessary to fetch the new remote reference, and remove the non-existent depot-branch reference. This can be accomplished in one step:

  4. Fetch the newly created Git branch reference, and remove local remnants from the previous operation:

    $ git fetch --prune origin

    Note

    A typical git push will continue to create a lightweight branch in Perforce. In this case, no pruning is necessary.

  5. Review the repo-specific p4gf_config file to see the new branch mapping created by Git Fusion.

Create a fully populated branch every time a Git user pushes a new branch

If you want Perforce users to be able to instantly use all new branches pushed by Git users, you can elect to create fully-populated branches in Perforce whenever Git users push a new branch.

  1. Enable depot branch creation in the global or repo-specific p4gf_config file with the all value.

    Use the global configuration file to enable this option for all repos or a repo-specific configuration file to enable it repo-by-repo.

    [git-to-perforce]
    depot-branch-creation-enable = all

    For additional configuration options, see the depot-branch-creation-* keys in Table 2, “Global configuration file: keys and default values”

  2. In Git, create a new branch.

    $ git checkout -b new_branch

  3. Push the new branch as usual to create a fully-populated branch in Perforce:

    $ git push [--set-upstream] origin new_branch

    This creates a new fully-populated branch in the Perforce depot and maps it to the Git branch, new_branch:

    //depot/my_project/new_branch/...

    The optional --set-upstream connects local branch reference new_branch to remote new_branch to reduce the amount of typing required for future pulls or pushes.

    A push to a branch name that already exists must be a fast-forward push, the same as pushes to master or any other branch. Otherwise the push is rejected. A Git user who unknowningly pushes a branch name that already exists must choose a different name, or rebase their new history on top of the existing branch’s head.

    Note

    Lightweight branches may still be created where needed for accurate representation and recreation of Git merge commits.

  4. Review the repo-specific p4gf_config file to see the new branch mapping created by Git Fusion.

Controlling depot location of pushed branches

Git Fusion uses depot-branch-creation-depot-path to determine where within Perforce to create the new branch. Git Fusion takes the value for this setting, performs string substitutions, and uses the result as the root to hold the pushed files.

There are three string substitutions:

  • {repo}: The name of the Git Fusion repo receiving this push.

  • {git_branch_name}: The name of the pushed branch reference.

  • {user}: The Perforce user ID of the pusher.

Examples

Example: project/branch hierarchy in Perforce

The common and default path omits user, uses the project name as the container for all branches on that project:

depot-branch-creation-depot-path = //depot/{repo}/{git_branch_name}

[email protected]$ git push https://syrinx/project task:dirks_task
^^^^                                 ^^^^^^^      ^^^^^^^^^^^
user                                 repo         git_branch_name

... creates ...

[pjfda2uh4rgzdixseowlk4zfki]
git-branch-name = dirks_task
view = //depot/project/dirks_task/... ...
               ^^^^^^^ ^^^^^^^^^^
               repo    git_branch_name
Example: Give each developer their own area in the Perforce depot.

Let each Git user have their own area under //dev/{user}/... to hold their own branches:

depot-branch-creation-depot-path = //dev/{user}/{repo}/{git_branch_name}

[email protected]$ git push https://syrinx/project task:dirks_task
^^^^                                 ^^^^^^^      ^^^^^^^^^^^
user                                 repo         git_branch_name

... creates ...

[bzkrk5p3yvcjzjxo6ikfajzoaq]
git-branch-name = dirks_task
view = //dev/dirk/project/dirks_task/... ...
             ^^^^ ^^^^^^^ ^^^^^^^^^^
             user repo    git_branch_name

Creates a new branch dirks_task in the Git Fusion repo, visible to all Git users, and mapped to Perforce location //dev/dirk/project/dirks_task/....

Example: {user} without {git_branch_name}

It is possible, but highly unlikely, that you want depot paths to include the user who created them, but not the Git branch name:

depot-branch-creation-depot-path = //depot/{repo}/{user}

[email protected]$ git push https://syrinx/project task:dirks_task
^^^^                                 ^^^^^^^      ^^^^^^^^^^^
user                                 repo         git_branch_name

... creates ...

[tk5kurabcfeovhkadywgdxv6xq]
git-branch-name = dirks_task
view = //depot/project/dirk/... ...
               ^^^^^^^ ^^^^
               repo    git_branch_name

The lack of {git_branch_name} limits each user to a single branch per repo, because any attempt to create a second branch will map to the same path as the first, and Git Fusion will reject the push because Perforce already has files on that path:

$ git push https://syrinx/project task2:dirks_task2
Username for 'https://syrinx': dirk
Password for 'https://[email protected]':
Counting objects: 3, done.
Writing objects: 100% (3/3), 226 bytes | 0 bytes/s, done.
Total 3 (delta 0), reused 0 (delta 0)
remote: Perforce: Cannot create new depot branch for ref 'refs/heads/dirks_task2':
  Git depot root '//depot/project/dirk' already contains Perforce changelists.
To https://syrinx/project
 ! [remote rejected] task2 -> dirks_task2 (pre-receive hook declined)
error: failed to push some refs to 'https://syrinx/project'

Working with Perforce streams

You can expose a Perforce stream as a branch view within a Git Fusion repo, allowing Git users to work with that branch and have that work submitted to Perforce as work within that stream. There are two ways to map a Git Fusion repo to a stream:

  • Clone using the stream name as the repo name.

    git clone https://git_fusion_server/stream_name

    If there is no Git Fusion repo with the name stream_name, Git Fusion searches for:

    • An existing Perforce workspace (client) with the name stream_name.

    • An existing Perforce stream with the name //stream_name.

    If Git Fusion finds a workspace, and that workspace is a stream workspace, then Git Fusion creates a repo with a single branch that maps that stream.

    If Git Fusion finds a stream, then Git Fusion creates a repo with a single branch that maps that stream.

    Note that Git would be confused by the // stream name prefix, so you must omit it from the clone command. Git can handle the internal /, but it will be translated to _0xS_ when the repo name is constructed. For example, if you clone using stream //flow/mainline, you use git clone https://gfserver/flow/mainline and get a repo named flow_0xs_mainline.

  • Add a stream to the branch definition in a repo's p4gf_config file.

    [my_new_branch]
    git-branch-name : my_new_branch
    stream : //streamdepot/my_stream

    Note that a stream branch does not include a view (there is no path on the "right hand side"), because the view is determined by the stream. A branch definition containing both stream and view will be rejected by the config file validator.

You must consider the following when you use streams with Git Fusion:

  • You can include only one stream per branch (although you can use a stream that imports other streams).

  • You can include both standard view-based branches and stream-based branches in the same repo.

  • You cannot base a git branch on a task stream.

  • You cannot change the stream view of a stream that is mapped to a Git branch.

    Git Fusion rejects pushes to Git branches whose stream view has changed since the repo was initialized.

  • Git users can merge between standard view-based branches and stream-based branches.

    This means that you can "drive through the hedges," merging and copying between streams that do not have a parent-child relationship.

  • Every branch mapping in Git Fusion must have the same right-hand side. Streams (other than mainline) with exclusionary lines or other remapping operations tend to produce different right-hand sides.

Enabling stream import paths as Git submodules

Git Fusion lets you represent stream import paths as Git submodules. In Perforce streams, import paths enable you to source files into a stream from different locations in the Perforce repository. Files included by import can be synced but not submitted, merged, or copied. Import paths are intended for situations when you want to include external libraries that you do not need to edit, such as those required for builds. Git submodules fill a similar role, allowing foreign repositories to be embedded within a dedicated subdirectory of the source tree.

Some considerations:

  • Submodules generated from import paths are read-only; you cannot push changes to them.

  • The process does not work in reverse: adding a submodule to a stream-based branch in Git does not add an import path to the stream.

  • For environments with multiple Git Fusion instances, be aware that submodules generated from import paths use a single Git Fusion instance as their remote.

    Ensure that users of a repo containing such a submodule can access the Git Fusion instance that is set as the submodule's remote.

Configure and generate submodules from import paths

To enable the conversion of stream import paths to Git submodules:

  1. Set the enable-git-submodules option to Yes in the repo configuration file.

    To enable import paths as submodules for all Git Fusion repos, set the option in the global configuration file. For individual repos, set the option in the repo-specific file.

    For more information, see Configuring global defaults for repos andConfigure repos with a repo configuration file (p4gf_config).

  2. Add the SSH or HTTP address you use to clone Git Fusion repos to the repo configuration file.

    Set the ssh-url or http-url property in the global configuration file if you are enabling submodules for all Git Fusion repos. For individual repos, set the property in the repo-specific file.

    Important

    • For any given repo, you can select only one protocol (SSH or HTTP) at a time.

      If at any point you need to switch from one protocol to another, you can update this configuration, but you must also edit the .gitmodules_stream-name file in the Perforce depot.

    • If you use the {host} variable in the URL property, submodule processing will use the hostname returned by the Linux function gethostname(). Verify that the value returned is the correct URL for running Git commands against the Git Fusion repo. Some network topologies can result in the return of unexpected values. Use the full hostname rather than the variable placeholder if you are not confident that the value returned will be correct.

  3. Define a repo branch using a stream with an import path.

    The stream must observe the following rules:

    • It must include a share... path.

    • It cannot include nested or overlapping import paths.

      If the stream imports from another stream that itself includes an import path or includes multiple import paths that share the same directories, Git Fusion treats these nested or overlapping paths as ordinary stream paths and does not convert them into submodules.

    • The stream depot path must be populated and end with /... .

    • You cannot change the stream root after the Git repo is initialized.

    For more information about defining repo branches using streams, see Working with Perforce streams.

  4. To generate the submodules, clone the repo you created in the previous step.

    The repo will include submodules with names derived from the depot path. The naming convention is to drop the depot path's initial // and terminal /... and replace any internal slashes with _0xS_. For example, a submodule generated from the import path //foo/bar/... would have the name foo_0xS_bar.

Managing and troubleshooting submodules

What are these new virtual streams that appear in the stream depot?

Git Fusion uses virtual streams as an intermediary in the creation of submodules from import paths. The virtual stream is created with the same name as its parent, with the addition of a _p4gfv suffix. Do not remove these virtual streams from the stream depot.

How do I change the submodule URL (ssh-url, http-url)?

If the value of ssh-url or http-url in the repo configuration file returns the wrong URL, Git Fusion cannot create submodules that work.

To fix the URL:

  1. Set ssh-url or http-url in the repo configuration file to the correct URL.

    If you are having issues generating submodules from stream import paths, it is often because the {host} variable placeholder is returning the wrong hostname. Use the full hostname rather than the variable placeholder.

    For more information, see Configure and generate submodules from import paths.

  2. Edit the .gitmodules file to update the submodule URL.

    The .gitmodules file is located in the top-level directory of your Git working tree and at the stream root in the Perforce. In Perforce, the file is stored with the suffix _stream-name.

  3. Update your clone by pulling and running git submodule update.

    Perform this command for each Git client that has attempted to clone the repo.

How do I remove submodules generated from import paths?

If an import path is removed from the stream definition, Git Fusion removes the associated submodule from the Git repo the next time a user pulls from that repo.

Adding preflight commits to reject pushes

If your Perforce service is configured with submit triggers that enforce a local policy, like requiring jobs, specific content, or specific formatting in the changelist description, these triggers can interrupt Git Fusion in the middle of a push, which will damage the repository as replicated within Perforce. You could simply exclude changes that are submitted by git-fusion-user from these submit triggers, but you can also create preflight commits (scripts that fire when a user attempts to push a commit to a Git Fusion repo) that reject git pushes before they have a chance to set off a potentially damaging submit trigger.

Preflight commit scripts can be written much the same way as Perforce trigger scripts, which gives you the option to reuse trigger scripts (or revise them minimally) to enforce local policy before Git Fusion submits the push to Perforce.

To enable a pre-flight commit:

  1. Create the script and save it to the server that hosts Git Fusion.

    Guidelines include the following:

    • Exit code 0 = pass (the push goes through), 1 = fail (reject the push)

    • The script must be run by the same UNIX account that runs Git Fusion (the Git Fusion service account), under the same environment.

    • The script is not invoked with a full shell, but it has access to the following environment variables:

      CWD

      Git work tree directory (parent of .git directory)

      P4PORT

      Perforce service (myperforceserver:port)

      P4USER

      git-fusion-user

      P4CLIENT

      git-fusion-repo_name

    • The script can consume the following Git Fusion variables:

      repo

      Name of the pushed repo

      sha1

      Full 40-character hexadecimal sha1 of a single commit

      branch_id

      Unique identifier for the Git Fusion branch view receiving this commit

      git-branch-name

      Git branch ref (if any) associated with above branch view

    • The script can consume the following standard Perforce trigger variables:

      client

      The client issuing the command. Always git-fusion-repo.

      clienthost

      Hostname of the client. Always the SSH client connection.

      serverport

      IP address:port of the server. Always the P4PORT that Git Fusion uses.

      quote

      A double quote character

      user

      User issuing the command. This is the P4USER associated with the commit's changelist owner: either Git author or Git pusher, depending on the repo configuration options.

      formfile

      Path to temp file containing form.

      formname

      The form's name (branch name, etc). Always new.

      formtype

      The type of form (branch, etc) Always change.

      jobs

      List of job names for fix triggers.

    See the preflight-commit-require-job.py and preflight-commit-require-case.py sample scripts in your libexec directory for examples.

    For more information about Perforce trigger scripts and variables, see the Perforce System Administrator's Guide, "Scripting Perforce: Triggers and Daemons".

  2. Add the script to the global configuration file or a repo-specific file, using the preflight-commit key.

    Use the syntax command argument, where command is the path to the script. Arguments can include any of the variables listed above, using the convention %variable%, as in the following example:

     [@repo]
     preflight-commit = /home/git/myscript.sh %repo% %sha1%

    Multiple scripts may be run in the configured order. All scripts must pass or the commit is rejected.

     [@repo]
     preflight-commit = /home/git/myscript1.sh %repo% %sha1%
                        /home/git/myscript2.sh %repo% %sha1% %git-branch-name%

    For more information about global and repo-specific configuration files, see Configuring global defaults for repos and Configure repos with a repo configuration file (p4gf_config).

Limiting push size and disk usage

In certain cases, large pushes from Git to Git Fusion can have undesireable effects.

  • Pushes to Git Fusion are immediately stored in Perforce, where history is purposely immutable. Extensive history can be easily added, but difficult to back out.

  • A large push can impact performance of the Git Fusion server and Perforce server, that possibly affects other users.

  • A large push can consume a significant amount of disk space on the Git Fusion server and Perforce server, and lead to longer backup, data replication, and maintenance times.

  • In a SaaS environment, extra resource usage can incur direct costs.

To curtail these effects, an administrator may wish to constrain the amount of data that can be pushed from Git to Git Fusion at any one time, or in total.

Limits for a single push

Git Fusion offers the ability to restrict pushes which exceed various quotas defined in Git Fusion configuration files.

  • These quotas are set by using the following configuration options, under the [quota] category:

    • limit_space_mb

    • limit_commits_received

    • limit_files_received

    • limit_megabytes_received

  • Any combination of these configuration options is allowed, however each additional metric requires some additional processing time.

  • The defaults for all quotas are zero, effectively disabling quota enforcement.

  • Like most options, these can be set in either the global or repo config file. For detailed usage of the above configuration options, see Table 2, “Global configuration file: keys and default values”.

Limit total Git Fusion disk usage

It is also possible to limit the total size of all repos managed by Git Fusion. To facilitate this limitation, an administrator sets, and Git Fusion respects, a Perforce p4 key named git-fusion-space-remaining-mb that defines the remaining number of megabytes permitted to be pushed to Git Fusion.

  • The format of the value may be either a natural number or a decimal fraction. That is, the administrator may set this to a natural number, and as Git Fusion processes push operations, fractional amounts will be subtracted from this value.

  • This value is only ever decreased by Git Fusion, and only when a push has been successfully completed.

  • Note that Git Fusion only measures the Git repository usage, and not the disk usage in the Perforce server. There are simply too many factors involved to permit making any reasonable estimate, and as such, only an administrator will have the necessary information to determine and set any usage limit.

To set a value for the git-fusion-space-remaining-mb key:

  1. Disable new Git Fusion sessions

    $ p4 key -i git-fusion-prevent-new-sessions

  2. Wait for all pending pull/push operations to finish (i.e. no keys are returned by the command below)

    $ p4 keys -e git-fusion-view-*-lock

  3. Set the git-fusion-space-remaining-mb key to the desired overall space limit (measured in megabytes)

    $ p4 key git-fusion-space-remaining-mb 1000

  4. Re-enable new Git Fusion sessions

    $ p4 key -d git-fusion-prevent-new-sessions

View current disk usage

In addition to standard shell and Git commands already available to administrators, Git Fusion offers two convenient ways to view repo disk usage.

  • Perforce p4 keys store the current size in megabytes of each repo that Git Fusion manages, as well as the size of any push which is currently going on. To view these sizes, run the following commands from any host with access, substituting the desired repo name:

    $ p4 key git-fusion-view-repo-total-mb
    $ p4 key git-fusion-view-repo-pending-mb
  • The script p4gf_push_limits.py can be run interactively on any Git Fusion server to display what is known about the available Git Fusion repositories, including the values in the total and pending keys as well as the disk usage of the repo on the Git Fusion host on which the script is currently running. Additionally, this script can be used to update the total and pending keys to reflect the current reality.

Detecting Git copy/rename and translating to Perforce

You can elect to honor Git's reported file actions for copy and rename when pushing repos into Perforce via Git Fusion.

By default Git Fusion does not detect Git copy/rename.

  • A file copied in Git will result in a p4 add in Perforce.

  • A file renamed in Git will result in a p4 delete and a p4 add in Perforce.

Git itself does not record copy/rename actions.

  • Git records file state, not file actions to change that state.

  • To report file actions, Git compares before/after states, then deduces file actions.

  • To detect copy/rename actions, Git scans before/after file lists looking for matching content, and if found, reports as a copy or rename.

Git copy/rename detection and translation into Perforce is enabled by two configuration options.

  • With these options enabled, Git Fusion uses Git’s --find-copies and --find-renames.

  • Git provides detection of copy/rename for less than identical files by setting the options to values < 100% and Git Fusion translates the results into the corresponding Perforce actions.

  • Perforce retains file history across depot branches. Copy or rename actions remain recorded in the branch where they occurred.

  • These options are disabled by default.

  • Like most options, these can be set in either the global or repo config file. For additional configuration options, see the enable-git-find-copies and enable-git-find-renames keys in Table 2, “Global configuration file: keys and default values”.

What happens when Git guesses incorrectly?

  • False Negative: Git misses a copy or rename action. The intention is lost. No integration between associated files is added to Perforce.

    • Copy is recorded as p4 add.

    • Rename is downgraded to a p4 delete and p4 add pair.

  • False Positive: Git reports a copy or rename where none was intended. An association is inferred where none was intended. Perforce records an integration between two files that are similar in content.

    • Copy creates a p4 copy link between a new file and a similar existing file.

    • Rename creates a p4 move link between a new file and a similar existing file that is deleted in the same commit.

  • Guesses cannot be backed out. Perforce history is purposely immutable. Once Git Fusion records a commit with Git's bad guess, the erroneous integration (or lack of integration) is part of history forever. Editing past history in Perforce is difficult: p4 obliterate, checkpoint surgery, and/or a call to Perforce Support is required.

Disconnecting a Git Fusion repo from the Perforce service

You can sever a Git Fusion repo's connection to Perforce and retain the repo.

To sever the repo’s connection:

  1. Copy the Git Fusion repo directory from ~/.git-fusion/views/repo_name/git to a location outside of .git-fusion.

  2. Delete .git/hooks/pre-receive from the repo copy.

After you copy the Git Fusion repo directory, you can delete the original repo from Git Fusion by running the Git Fusion Delete Repo script (p4gf_delete_repo.py).

Deleting Git Fusion repos

To delete Git Fusion repos from Perforce, use the Git Fusion Delete Repo script (p4gf_delete_repo.py).

Important

Whenever you run p4gf_delete_repo.py, you should also run p4gf_submit_trigger.py --reset myperforceserver:port.