Using git-p4

From LSDevLinux
Jump to: navigation, search

Using git as a front-end to the Perforce FieldWorks repository.

While p4v has many good features, some developers may be more comfortable using a different front-end to the Perforce FieldWorks repository, such as git-p4. Note that you will still need a Perforce checkout on your machine for git-p4 to commit back to Perforce (see Build_FieldWorks#Check_out_from_VCS for information on checking out from Perforce).

Install git-p4

Install dependencies

Install p4

The latest version of p4 can be found at

$ cd $(mktemp -dt)
$ wget ''
$ sudo install p4 /usr/local/bin

Append to ~/.bashrc:

export P4CLIENT=your_workspace_name
export (or hydra:1935)
export P4USER=your_username (or anonymous)

Close and re-open your terminal.


~$ git clone git://

Link to the git-p4 script from a directory in your PATH, such as ~/bin:

$ mkdir -p ~/bin && cd ~/bin
bin$ ln -s ~/git-p4/git-p4

Set git-p4 to work with file renames/integrations:

$ git config --global git-p4.detectRename true

Updating git-p4

To update git-p4, do

$ cd ~/git-p4
git-p4$ git pull

Setup Gerrit

Follow the setup steps on the wiki page to create a Gerrit username.

Check out repository using git-p4

Prepare a place for the code:

$ mkdir -p ~/gp/Calgary
$ cd ~/gp/Calgary

Clone the git repo including the git-notes that contain the references to Perforce:

gp/Calgary$ git clone ssh://<gerritusername> FW70

If you don't have and don't want an account on Gerrit, you can use this clone command:

gp/Calgary$ git clone FW70

Additionally you need to set up some options in git. This is easiest done by cloning fieldworks-build and then running initp4git:

gp/Calgary$ git clone git://
gp/Calgary$ cd FW70
gp/Calgary/FW70$ ../fieldworks-build/initp4git

After having set up the required options you need to fetch the additional branches:

gp/Calgary/FW70$ git fetch origin

You also need to have a p4 client spec set before you can submit. This can either be set through the P4CLIENT environment variable, or you can add the information in the git config file:

gp/Calgary/FW70$ git config git-p4.client myclientname

In the gp/Calgary directory, you will need COM, Win32Base, and Win32More, or symlinks to them if they are already checked out elsewhere. See Build_FieldWorks#Check_out_libcom_from_svn for information on checking out libcom from svn.

If you already have COM, Win32Base, and Win32More checked out where Build_FieldWorks#Check_out_libcom_from_svn prescribes, then you can just symlink to them by doing:

gp/Calgary$ for dir in ~/p4repo/Calgary/{COM,Win32Base,Win32More}; do ln -s $dir; done


There is a readme about a different version of git-p4 at .

Updating and pushing

Your workflow might look like:

1. Get latest version from git

$ git fetch origin && git pull origin

2. Create a topic branch

$ git checkout -b mytopic

3. Edit files

$ vim foo.cs

4. Commit changes locally to git

$ git commit

5. When you're ready for code review submit the changes to Gerrit

$ git review master

6. Have someone review the code in Gerrit (but not submit)

7. When you're ready to submit to Perforce, go to Gerrit web site and submit your change (press Submit button). Gerrit merges the change to master branch. If this fails, then see below.

8. Submit changes to Perforce and update Gerrit's remote repo

$ git p4su

9. Delete topic branch

$ git branch -d mytopic

If submitting in Gerrit fails (step 7) with a message "Project policy requires all submissions to be a fast-forward" you need to get the latest P4 changes first, rebase your changes and re-submit them to Gerrit. Then continue with step 7 above.

$ git checkout master
$ git fetch && git pull origin master
$ git checkout mytopic
$ git rebase master
$ git review master

With a topic branch


If your master is tracking remotes/p4/master, you made a topic branch "crashbug" from master to work on a bug or feature, and you've made several commits to crashbug but don't want to push all of them since they aren't all ready, but you do want to push just one or two right now, you can push by: (Note: This is if not using gerrit)

# Cherry pick some_commit from crashbug:
$ git checkout master && git fetch origin && git pull origin master && git cherry-pick some_commit
$ git p4su
$ git checkout crashbug && git rebase master

Sending for Code Review by email rather than using Gerrit

You are on a topic branch based on remotes/p4/master, and you want all commits in the branch to be sent for code review.

$ git p4 rebase # Then make sure it is still what you want to send for review.
$ tinydesc="couple-word description"
$ myaddr=""
$ toaddr=""
$ server=""
$ git send-email --compose --subject="Code Review for $tinydesc" --subject-prefix="$tinydesc patch" \
  --to=$toaddr --smtp-server=$server --from=$myaddr --cc=$myaddr remotes/p4/master..

This can of course all be simplified with configuration files etc.


Protecting csproj files

Since your files are read-write by default when you use git-p4 (rather than read-only when using p4v), you may want to protect .csproj files sometimes so that monodevelop does not rewrite them when you don't want it to. (Though this may make monodevelop unsuccessful at managing your solution file.) You can easily do that by running:

gp/Calgary/WW$ find -name \*csproj -print0 | xargs -0 chmod u-w

To make a csproj writable again, run:

gp/Calgary/WW$ chmod u+w Src/Foo/Baz.csproj

It may be easier to edit the csproj by hand depending on what you want to change.

Git GUI tools

There are numerous git GUI tools available.

You may find it helpful to browse and view history using gitk and make commits and manage your index using git-cola.

Resolving conflicts

If you have work on an old branch, check out that branch and run git rebase master, it may not cleanly apply, saying:

CONFLICT (content): Merge conflict in Src/Foo.cs
Failed to merge in the changes.
Patch failed at 0002 My Patch

Or if you merge a branch into another branch, it may not merge cleanly, saying:

CONFLICT (content): Merge conflict in Src/Foo.cs
Automatic merge failed; fix conflicts and then commit the result.

To resolve the conflicts from your merge or rebase, try:

$ sudo aptitude install git-cola kdiff3-qt
$ git config --global --add merge.conflictstyle diff3
$ git-cola &

Choose Edit > Options. In the Merge Tool box, enter kdiff3 and click Save. In the Repository Status pane, click a file in the Unmerged section. The Diff Viewer pane will show something like:

   public void DoSomething()
++<<<<<<< HEAD
 +   if (!true)                           // Their modification
 +     return;
++   throw new NotImplementedException(); // Original code
+    if (!true)                           // Your modification
+      throw new Exception();
++>>>>>>> My Patch

The lines between ||||||| and ======= is the original code. You modified it to say what's between ======= and >>>>>>> My Patch, while someone else (possibly you) modified it to say what's between <<<<<<< HEAD and |||||||.

Right-click the file in the Unmerged section and choose Launch Merge Tool. Use kdiff3 to resolve the merge conflicts (Learn about kdiff3 here and here). Choose File > Save, File > Quit.

Do this for each file in the Unmerged section in git-cola. When you are finished, if git-cola didn't update all the way on its own, choose File > Rescan.

(Note that when you quit kdiff3, git-cola might print "fatal: Unable to create '/home/user/gp/Calgary/WW/.git/index.lock': File exists." to the terminal. If so, you could close and reopen git-cola and resolve that conflict again, or you might be able to click the file in the Unmerged section and click Stage.)

Examine the diffs in the Staged section.

Do one of the following:

  • If rebasing, choose File > Quit. In the terminal, type:
$ git rebase --continue
  • If merging, modify the commit message in git-cola and click Commit. Choose File > Quit.