summaryrefslogtreecommitdiff
path: root/contrib/fast-import/git-p4.txt
blob: b16a8384bcfbfe33dc33e1076c64f5d36e75e803 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
git-p4 - Perforce <-> Git converter using git-fast-import

Usage
=====

git-p4 supports two main modes: Importing from Perforce to a Git repository is
done using "git-p4 sync" or "git-p4 rebase". Submitting changes from Git back
to Perforce is done using "git-p4 submit".

Importing
=========

You can simply start with

  git-p4 clone //depot/path/project

or

  git-p4 clone //depot/path/project myproject

This will create an empty git repository in a subdirectory called "project" (or
"myproject" with the second command), import the head revision from the
specified perforce path into a git "p4" branch (remotes/p4 actually), create a
master branch off it and check it out. If you want the entire history (not just
the head revision) then you can simply append a "@all" to the depot path:

  git-p4 clone //depot/project/main@all myproject



If you want more control you can also use the git-p4 sync command directly:

  mkdir repo-git
  cd repo-git
  git init
  git-p4 sync //path/in/your/perforce/depot

This will import the current head revision of the specified depot path into a
"remotes/p4/master" branch of your git repository. You can use the
--branch=mybranch option to use a different branch.

If you want to import the entire history of a given depot path just use

  git-p4 sync //path/in/depot@all

To achieve optimal compression you may want to run 'git repack -a -d -f' after
a big import. This may take a while.

Support for Perforce integrations is still work in progress. Don't bother
trying it unless you want to hack on it :)

Incremental Imports
===================

After an initial import you can easily synchronize your git repository with
newer changes from the Perforce depot by just calling

  git-p4 sync

in your git repository. By default the "remotes/p4/master" branch is updated.

It is recommended to run 'git repack -a -d -f' from time to time when using
incremental imports to optimally combine the individual git packs that each
incremental import creates through the use of git-fast-import.


A useful setup may be that you have a periodically updated git repository
somewhere that contains a complete import of a Perforce project. That git
repository can be used to clone the working repository from and one would
import from Perforce directly after cloning using git-p4. If the connection to
the Perforce server is slow and the working repository hasn't been synced for a
while it may be desirable to fetch changes from the origin git repository using
the efficient git protocol. git-p4 supports this setup by calling "git fetch origin"
by default if there is an origin branch. You can disable this using

  git config git-p4.syncFromOrigin false

Updating
========

A common working pattern is to fetch the latest changes from the Perforce depot
and merge them with local uncommitted changes. The recommended way is to use
git's rebase mechanism to preserve linear history. git-p4 provides a convenient

  git-p4 rebase

command that calls git-p4 sync followed by git rebase to rebase the current
working branch.

Submitting
==========

git-p4 has support for submitting changes from a git repository back to the
Perforce depot. This requires a Perforce checkout separate to your git
repository. To submit all changes that are in the current git branch but not in
the "p4" branch (or "origin" if "p4" doesn't exist) simply call

    git-p4 submit

in your git repository. If you want to submit changes in a specific branch that
is not your current git branch you can also pass that as an argument:

    git-p4 submit mytopicbranch

You can override the reference branch with the --origin=mysourcebranch option.

If a submit fails you may have to "p4 resolve" and submit manually. You can
continue importing the remaining changes with

  git-p4 submit --continue

After submitting you should sync your perforce import branch ("p4" or "origin")
from Perforce using git-p4's sync command.

If you have changes in your working directory that you haven't committed into
git yet but that you want to commit to Perforce directly ("quick fixes") then
you do not have to go through the intermediate step of creating a git commit
first but you can just call

  git-p4 submit --direct


Example
=======

# Clone a repository
  git-p4 clone //depot/path/project
# Enter the newly cloned directory
  cd project
# Do some work...
  vi foo.h
# ... and commit locally to gi
  git commit foo.h
# In the meantime somebody submitted changes to the Perforce depot. Rebase your latest
# changes against the latest changes in Perforce:
  git-p4 rebase
# Submit your locally committed changes back to Perforce
  git-p4 submit
# ... and synchronize with Perforce
  git-p4 rebase


Implementation Details...
=========================

* Changesets from Perforce are imported using git fast-import.
* The import does not require anything from the Perforce client view as it just uses
  "p4 print //depot/path/file#revision" to get the actual file contents.
* Every imported changeset has a special [git-p4...] line at the
  end of the log message that gives information about the corresponding
  Perforce change number and is also used by git-p4 itself to find out
  where to continue importing when doing incremental imports.
  Basically when syncing it extracts the perforce change number of the
  latest commit in the "p4" branch and uses "p4 changes //depot/path/...@changenum,#head"
  to find out which changes need to be imported.
* git-p4 submit uses "git rev-list" to pick the commits between the "p4" branch
  and the current branch.
  The commits themselves are applied using git diff/format-patch ... | git apply