push: point to 'git pull' and 'git push --force' in case of non-fast forward
'git push' failing because of non-fast forward is a very common situation, and a beginner does not necessarily understand "fast forward" immediately. Add a new section to the git-push documentation and refer them to it. Signed-off-by: Matthieu Moy <Matthieu.Moy@imag.fr> Signed-off-by: Junio C Hamano <gitster@pobox.com> Signed-off-by: Nanako Shiraishi <nanako3@lavabit.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Matthieu Moy committed
Aug 8, 2009 at 09:51 UTC
07436e43daf1a97d3d702090d6289f745bd5ad90
4 files changed
+103
-5
Documentation/git-push.txt
+86
@@ -195,6 +195,92 @@ reason::
195
refs, no explanation is needed. For a failed ref, the reason for
196
failure is described.
197
198
+Note about fast-forwards
199
+------------------------
200
+
201
+When an update changes a branch (or more in general, a ref) that used to
202
+point at commit A to point at another commit B, it is called a
203
+fast-forward update if and only if B is a descendant of A.
204
+
205
+In a fast-forward update from A to B, the set of commits that the original
206
+commit A built on top of is a subset of the commits the new commit B
207
+builds on top of. Hence, it does not lose any history.
208
+
209
+In contrast, a non-fast-forward update will lose history. For example,
210
+suppose you and somebody else started at the same commit X, and you built
211
+a history leading to commit B while the other person built a history
212
+leading to commit A. The history looks like this:
213
+
214
+----------------
215
+
216
+ B
217
+ /
218
+ ---X---A
219
+
220
+----------------
221
+
222
+Further suppose that the other person already pushed changes leading to A
223
+back to the original repository you two obtained the original commit X.
224
+
225
+The push done by the other person updated the branch that used to point at
226
+commit X to point at commit A. It is a fast-forward.
227
+
228
+But if you try to push, you will attempt to update the branch (that
229
+now points at A) with commit B. This does _not_ fast-forward. If you did
230
+so, the changes introduced by commit A will be lost, because everybody
231
+will now start building on top of B.
232
+
233
+The command by default does not allow an update that is not a fast-forward
234
+to prevent such loss of history.
235
+
236
+If you do not want to lose your work (history from X to B) nor the work by
237
+the other person (history from X to A), you would need to first fetch the
238
+history from the repository, create a history that contains changes done
239
+by both parties, and push the result back.
240
+
241
+You can perform "git pull", resolve potential conflicts, and "git push"
242
+the result. A "git pull" will create a merge commit C between commits A
243
+and B.
244
+
245
+----------------
246
+
247
+ B---C
248
+ / /
249
+ ---X---A
250
+
251
+----------------
252
+
253
+Updating A with the resulting merge commit will fast-forward and your
254
+push will be accepted.
255
+
256
+Alternatively, you can rebase your change between X and B on top of A,
257
+with "git pull --rebase", and push the result back. The rebase will
258
+create a new commit D that builds the change between X and B on top of
259
+A.
260
+
261
+----------------
262
+
263
+ B D
264
+ / /
265
+ ---X---A
266
+
267
+----------------
268
+
269
+Again, updating A with this commit will fast-forward and your push will be
270
+accepted.
271
+
272
+There is another common situation where you may encounter non-fast-forward
273
+rejection when you try to push, and it is possible even when you are
274
+pushing into a repository nobody else pushes into. After you push commit
275
+A yourself (in the first picture in this section), replace it with "git
276
+commit --amend" to produce commit B, and you try to push it out, because
277
+forgot that you have pushed A out already. In such a case, and only if
278
+you are certain that nobody in the meantime fetched your earlier commit A
279
+(and started building on top of it), you can run "git push --force" to
280
+overwrite it. In other words, "git push --force" is a method reserved for
281
+a case where you do mean to lose history.
282
+
283
+
284
Examples
285
--------
286
builtin-push.c
+8
-1
@@ -140,6 +140,7 @@ static int do_push(const char *repo, int flags)
140
struct transport *transport =
141
transport_get(remote, url[i]);
142
int err;
143
+ int nonfastforward;
144
if (receivepack)
145
transport_set_option(transport,
146
TRANS_OPT_RECEIVEPACK, receivepack);
@@ -148,13 +149,19 @@ static int do_push(const char *repo, int flags)
149
150
if (flags & TRANSPORT_PUSH_VERBOSE)
151
fprintf(stderr, "Pushing to %s\n", url[i]);
151
- err = transport_push(transport, refspec_nr, refspec, flags);
152
+ err = transport_push(transport, refspec_nr, refspec, flags,
153
+ &nonfastforward);
154
err |= transport_disconnect(transport);
155
156
if (!err)
157
continue;
158
159
error("failed to push some refs to '%s'", url[i]);
160
+ if (nonfastforward) {
161
+ printf("To prevent you from losing history, non-fast-forward updates were rejected.\n"
162
+ "Merge the remote changes before pushing again.\n"
163
+ "See 'non-fast forward' section of 'git push --help' for details.\n");
164
+ }
165
errs++;
166
}
167
return !!errs;
transport.c
+7
-3
@@ -820,7 +820,7 @@ static int print_one_push_status(struct ref *ref, const char *dest, int count, i
820
}
821
822
static void print_push_status(const char *dest, struct ref *refs,
823
- int verbose, int porcelain)
823
+ int verbose, int porcelain, int * nonfastforward)
824
{
825
struct ref *ref;
826
int n = 0;
@@ -835,11 +835,14 @@ static void print_push_status(const char *dest, struct ref *refs,
835
if (ref->status == REF_STATUS_OK)
836
n += print_one_push_status(ref, dest, n, porcelain);
837
838
+ *nonfastforward = 0;
839
for (ref = refs; ref; ref = ref->next) {
840
if (ref->status != REF_STATUS_NONE &&
841
ref->status != REF_STATUS_UPTODATE &&
842
ref->status != REF_STATUS_OK)
843
n += print_one_push_status(ref, dest, n, porcelain);
844
+ if (ref->status == REF_STATUS_REJECT_NONFASTFORWARD)
845
+ *nonfastforward = 1;
846
}
847
}
848
@@ -997,7 +1000,8 @@ int transport_set_option(struct transport *transport,
1000
}
1001
1002
int transport_push(struct transport *transport,
1000
- int refspec_nr, const char **refspec, int flags)
1003
+ int refspec_nr, const char **refspec, int flags,
1004
+ int * nonfastforward)
1005
{
1006
verify_remote_names(refspec_nr, refspec);
1007
@@ -1024,7 +1028,7 @@ int transport_push(struct transport *transport,
1028
1029
ret = transport->push_refs(transport, remote_refs, flags);
1030
1027
- print_push_status(transport->url, remote_refs, verbose | porcelain, porcelain);
1031
+ print_push_status(transport->url, remote_refs, verbose | porcelain, porcelain, nonfastforward);
1032
1033
if (!(flags & TRANSPORT_PUSH_DRY_RUN)) {
1034
struct ref *ref;
transport.h
+2
-1
@@ -68,7 +68,8 @@ int transport_set_option(struct transport *transport, const char *name,
68
const char *value);
69
70
int transport_push(struct transport *connection,
71
- int refspec_nr, const char **refspec, int flags);
71
+ int refspec_nr, const char **refspec, int flags,
72
+ int * nonfastforward);
73
74
const struct ref *transport_get_remote_refs(struct transport *transport);
75