aboutsummaryrefslogtreecommitdiff
path: root/contrib/fast-import/git-p4.txt
blob: 52003ae9045626077009811cd8e10c1135d69cd0 (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
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
git-p4 - Perforce <-> Git converter using git-fast-import

Usage
=====

git-p4 can be used in two different ways:

1) To import changes from Perforce to a Git repository, using "git-p4 sync".

2) To submit changes from Git back to Perforce, using "git-p4 submit".

Importing
=========

Simply start with

  git-p4 clone //depot/path/project

or

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

This will:

1) Create an empty git repository in a subdirectory called "project" (or
"myproject" with the second command)

2) Import the head revision from the given Perforce path into a git branch
called "p4" (remotes/p4 actually)

3) Create a master branch based on 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 import into a different branch.

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

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


Note:

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

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

After an initial import you can continue to 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.

Advanced Setup
==============

Suppose you have a periodically updated git repository somewhere, containing a
complete import of a Perforce project. This repository can be cloned and used
with git-p4. When updating the cloned repository with the "sync" command,
git-p4 will try to fetch changes from the original repository first. The git
protocol used with this is usually faster than importing from Perforce
directly.

This behaviour can be disabled by setting the "git-p4.syncFromOrigin" git
configuration variable to "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 from 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.

The Perforce changelists will be created with the user who ran git-p4. If you
use --preserve-user then git-p4 will attempt to create Perforce changelists
with the Perforce user corresponding to the git commit author. You need to
have sufficient permissions within Perforce, and the git users need to have
Perforce accounts. Permissions can be granted using 'p4 protect'.

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

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


Configuration parameters
========================

git-p4.user ($P4USER)

Allows you to specify the username to use to connect to the Perforce repository.

  git config [--global] git-p4.user public

git-p4.password ($P4PASS)

Allows you to specify the password to use to connect to the Perforce repository.
Warning this password will be visible on the command-line invocation of the p4 binary.

  git config [--global] git-p4.password public1234

git-p4.port ($P4PORT)

Specify the port to be used to contact the Perforce server. As this will be passed
directly to the p4 binary, it may be in the format host:port as well.

  git config [--global] git-p4.port codes.zimbra.com:2666

git-p4.host ($P4HOST)

Specify the host to contact for a Perforce repository.

  git config [--global] git-p4.host perforce.example.com

git-p4.client ($P4CLIENT)

Specify the client name to use

  git config [--global] git-p4.client public-view

git-p4.allowSubmit

  git config [--global] git-p4.allowSubmit false

git-p4.syncFromOrigin

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 [--global] git-p4.syncFromOrigin false

git-p4.useclientspec

  git config [--global] git-p4.useclientspec false

The P4CLIENT environment variable should be correctly set for p4 to be
able to find the relevant client.  This client spec will be used to
both filter the files cloned by git and set the directory layout as
specified in the client (this implies --keep-path style semantics).

git-p4.skipSubmitModTimeCheck

  git config [--global] git-p4.skipSubmitModTimeCheck false

If true, submit will not check if the p4 change template has been modified.

git-p4.preserveUser

  git config [--global] git-p4.preserveUser false

If true, attempt to preserve user names by modifying the p4 changelists. See
the "--preserve-user" submit option.

git-p4.allowMissingPerforceUsers

  git config [--global] git-p4.allowMissingP4Users false

If git-p4 is setting the perforce user for a commit (--preserve-user) then
if there is no perforce user corresponding to the git author, git-p4 will
stop. With allowMissingPerforceUsers set to true, git-p4 will use the
current user (i.e. the behavior without --preserve-user) and carry on with
the perforce commit.

git-p4.skipUserNameCheck

  git config [--global] git-p4.skipUserNameCheck false

When submitting, git-p4 checks that the git commits are authored by the current
p4 user, and warns if they are not. This disables the check.

git-p4.detectRenames

Detect renames when submitting changes to Perforce server. Will enable -M git
argument. Can be optionally set to a number representing the threshold
percentage value of the rename detection.

  git config [--global] git-p4.detectRenames true
  git config [--global] git-p4.detectRenames 50

git-p4.detectCopies

Detect copies when submitting changes to Perforce server. Will enable -C git
argument. Can be optionally set to a number representing the threshold
percentage value of the copy detection.

  git config [--global] git-p4.detectCopies true
  git config [--global] git-p4.detectCopies 80

git-p4.detectCopiesHarder

Detect copies even between files that did not change when submitting changes to
Perforce server. Will enable --find-copies-harder git argument.

  git config [--global] git-p4.detectCopies true

git-p4.branchUser

Only use branch specifications defined by the selected username.

  git config [--global] git-p4.branchUser username

git-p4.branchList

List of branches to be imported when branch detection is enabled.

  git config [--global] git-p4.branchList main:branchA
  git config [--global] --add git-p4.branchList main:branchB

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