-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathREADME-git
776 lines (643 loc) · 38.5 KB
/
README-git
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
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
README-git file for GASNet
http://gasnet.lbl.gov
The purpose of this document is to list practices that GASNet developers are
expected to follow when committing code to the public repository. It is a
companion to the coding standards and design documentation.
See also:
+ README: GASNet usage documentation
+ README-devel: GASNet design information and coding standards
+ README-release: Detailed release procedure
GASNet Revision Control Practices
=================================
* All developers doing commits must be on the gasnet-devel@lbl.gov email list,
which receives GASNet commit messages.
* You should commit only to the 'develop' branch - do NOT commit to 'master'
except for stable public releases (may include snapshots, etc. but NOT normal
day-to-day development work).
* Anything that is not a "trivial" change (such as correcting a typo or a small
1 or 2 line bug fix) should be performed on a "feature branch" and merged back
to 'develop' following the git-flow workflow as described in more detail later
in this document. This allows the "feature" to be developed over multiple
commits while clearly identifying the start and end of the work, preventing
interleaving of commits with the work of other developers, and provides a
commit message that can summarize the purpose of the change(s).
* When merging your feature branch to 'develop' don't include any extra changes
that might confuse a review, or be lost if your feature must be reverted. For
instance if during the merge you notice a bug in the feature, go back to the
branch and fix it before restarting the merge. If you encounter a bug, a typo
or other "issue" in 'develop' that is not related to your feature, then fix it
either before merging your branch (requiring an additional rebase), or else
fix it after your merge is completed.
* You must include an explanatory log message for every commit you make. It
should describe the high-level of what you did, and why you did it (e.g. to
solve a particular bug, etc). Generally larger changes deserve more detailed
log messages - remember the idea is to keep other developers apprised of
changes you've made that could affect their work somehow. Commit messages
should reference any particular bug ID's that they address. When doing work
as multiple commits to a feature branch, this rule applies NOT only to the
final merge commit, but also to the individual commits on the branch which
should each be reviewable individually. Remember that somebody you've never
met may read your log message years after you write it. So, make everything
explicit, avoiding phrases like "Apply Jane's idea from last week's meeting".
* The rule on log messages above applies to anything that will become publicly
visible. For your work in a local git repo you are welcome to practice any
discipline that works for you. HOWEVER, when it is time to merge work back to
'develop' one should use git to edit commit messages or squash commits to
ensure your work meets these standards. Anything on 'develop' is
world-visible.
* To ensure things work nicely with all of the git-related tools, log messages
should follow the format (without the leading 5 columns of indent) of the
canonical model below, taken from
http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html
---begin example---
Capitalized, short (50 chars or less) summary
More detailed explanatory text, if necessary. Wrap it to about 72
characters or so. In some contexts, the first line is treated as the
subject of an email and the rest of the text as the body. The blank
line separating the summary from the body is critical (unless you omit
the body entirely); tools like rebase can get confused if you run the
two together.
Write your commit message in the imperative: "Fix bug" and not "Fixed bug"
or "Fixes bug." This convention matches up with commit messages generated
by commands like git merge and git revert.
Further paragraphs come after blank lines.
- Bullet points are okay, too
- Typically a hyphen or asterisk is used for the bullet, followed by a
single space, with blank lines in between, but conventions vary here
- Use a hanging indent
---end example---
In the case of a "Merge branch ..." commit, it is often helpful to to include
the 50-character summaries from the commits that comprise the branch. The
message can be seeded with those summaries by passing "--log" to "git merge".
Similarly the commit message for a "git cherry-pick" can be seeded with the
SHA1 of the cherry-picked commit by passing "-x" (which should only be used
to reference commits which have been pushed to BitBucket).
* Our git repository at BitBucket is configure to DENY any history re-writes on
the 'develop' branch. This means you cannot 'git amend' or otherwise make
any modifications to history once you've pushed to 'origin/develop'. Keep
this in mind along with the fact that anything you push to the server is
visible to the entire world.
* You should only commit *working* code to 'develop' - do NOT commit untested or
flagrantly broken code that could affect system stability. The idea is to
ensure the 'develop' branch of the repository is mostly-working at all times.
To do otherwise renders the powerful 'git bisect' command essentially useless.
So, try to make sure your commits leave the repository in at least as working
a state as you found it. We understand that it may not be practical to test
a given change on all platforms, but you should at least test it thoroughly on
your development platform, and any other platforms that you have reason to
believe may be affected (this is especially true for configure scripts and
Makefiles).
* If you wish to share intermediate or untested versions of your code for review
or testing by other developers, you can push your feature branch to BitBucket.
Once there, a Pull Request can be used to provide a forum for review if this
is desired. However, we are not currently imposing any formal requirement for
use of Pull Requests.
* Whenever you "git add" any new (previously untracked) files to the
repository, make sure they also get added to the Makefile.am file (if any)
for the enclosing directory. Otherwise your added file won't be included in
the public release. Of course there are files (this developer documentation
for instance) which we don't distribute, but that is the UNcommon case.
* When we were using CVS, we recommended frequent use of tags, such as any time
you begin a branch or merge your branch to or from HEAD. This is not nearly
as necessary in git because there is always a hash to identify the state of
the entire repository after any given commit, and tools to find them easily.
Additionally our use of the git-flow workflow ensures that even after merging,
the sequence of commits that comprise a given feature branch is easily
identifiable (and therefore can quickly be reverted or applied to 'master' if
necessary). This is not to say that there is NO use for tags with git. They
are especially important when you want to be able to correlate points in time
across multiple repositories (e.g. a GASNet commit which provides a feature
required for Berkeley UPC).
* GASNet supports both a regular and tools-only (conduit-free) distribution.
The Bootstrap -o option activates tools-only mode for a given source tree
by MODIFYING several source files, but the git repo is always kept in regular
distribution mode. This means if you use tools-only mode, you MUST Bootstrap
back to regular mode (without -o) before committing any changes to the repo.
* All GASNet developers are required to follow the GASNet coding standards
outlined in README-devel.
GASNet's Git Workflow
=====================
The purpose of this section is to describe how git is to be used for GASNet
development, providing examples of the most common tasks. This assumes you
have a basic working knowledge of git and is not a full tutorial.
A note on proprietary (NDA) information
---------------------------------------
A stern reminder that a "git clone" includes the entire history of everything
that has ever existed in the public repo, and that this public repo is world
readable. So, you must NEVER "git push" anything to the public server (even to
a private branch that might be merged) that you don't have the rights to
publish. A detailed "protocol" for dealing with proprietary data (especially
that with an expiration date) will eventually be added to this document.
Requirements
------------
This documentation was written using git-1.8 and git-flow. Where known,
alternatives required for git-1.7 are included, but no effort has been expended
to back-port to older git releases. If future versions of git break these
instructions, we'll update this document appropriately.
Since GASNet is hosted on BitBucket.org you will require an account there if
you are going to push (upload) anything to the repository. Contact us at
gasnet-devel@lbl.gov to request Write permission for your BitBucket account.
Example commands in this document will be written like
$ git ...
consistent with the '$ ' prompt of a bash or other Bourne shell. The examples
should work with ANY standard (Bourne or csh family) command shell.
Overview of git-flow
--------------------
The GASNet project is following the git-flow model.
(See http://nvie.com/posts/a-successful-git-branching-model/)
The basic ideas:
+ A long-lived 'master' branch holds public releases, and should generally
have a tag for each commit. If something is not worthy of a tag, then it
probably doesn't belong in 'master').
This is the default branch for most *users* to find stable versions.
+ A long-lived 'develop' branch is used for continuous integration.
This is the branch *developers* should be working with.
+ Transient "feature branches" (off of 'develop') are used for work on each
task, and are merged to 'develop' (and then deleted) only when the work is
completed/tested. These branches may be published to a public server, but
often will exist only in the developer's local repository.
+ Transient "release branches" (also off of 'develop') are used to move work
from the 'develop' branch to 'master'. Ideally the only commits to a
release branch will be version number changes and related updates to
documentation. However this is also the place to fix "issues" found while
testing the release. When release preparation is complete, release branches
are merged to BOTH develop and master (and then deleted).
+ Transient "hotfix branches" are for fixing urgent issues in the code on
'master'. They work just like release branches except that they branch from
'master' instead of from 'develop'.
+ All branch merges are done following a rebase (to keep linear history) but
with --no-ff to force a "true merge" which preserves a clear start and end
to the commits from each feature branch.
The name "git-flow" refers to both the work-flow we have adopted AND to a set
of extensions to git which provide automation of many of the steps required to
follow the work-flow. Use of the git-flow extensions is entirely optional.
However, you will see in the remainder of this document there is much less to
remember (and type) if you do use git-flow. You can obtain git-flow from
github at
https://github.com/nvie/gitflow/wiki
To enable use the git-flow extensions, GASNet is using the branch names
"master" and "develop" to match the git-flow defaults. Similarly, the use of
"feature/", "release/" and "hotfix/" are strongly recommended when naming
branches of the corresponding types to match the git-flow defaults.
Git-flow is just a collection of wrappers around standard git operations, with
no hidden state or "magic". So, as long as the naming conventions for branches
is applied consistently, one can freely move between git-flow and plain git
commands to work on your repository. In particular, a branch which is created
with git-flow can safely be merged using plain git and vise versa.
Setup
-----
To clone the GASNet repo use either of the following:
$ git clone https://USER@bitbucket.org/berkeleylab/gasnet
or
$ git clone git@bitbucket.org:berkeleylab/gasnet.git
The first option (https) will require your password for every push, while the
second (ssh) requires that you upload an ssh public key to BitBucket. See
https://confluence.atlassian.com/display/BITBUCKET/Set+up+SSH+for+Git
for help with the key upload. If you have a suitable key already, you can
probably skip right to step #6.
If you do not have a BitBucket account then you can still clone the repo, but
will not be able to push your changes back. See the section "Forking
Development" for information on what you can do without Write access to the
repo.
As a developer, the first thing you probably want to do is:
$ git checkout develop
If your git is too old (prior to 1.7) for that command to work, try this:
$ git checkout --track -b develop origin/develop
BUT be warned that none of our git usage instructions have been tested
with anything older than git-1.7.
If you will be using the git-flow extensions you need to initialize git-flow.
Since we use the defaults for branch names, this just takes two steps:
$ git flow init -d
$ git config gitflow.prefix.versiontag gasnet-
Where the second ensures release tags of the form "gasnet-1.2.3". This step
only writes a few strings to .git/config, none of which impact use of the
standard git commands. If you are uncertain if you want to use git-flow it is
fine to defer this initialization until the first time you use "git flow ...".
If you've not been using git on this host before, you probably want to start
with the following to configure your name and email before you push anything:
$ git config --global user.name "Jane Doe"
$ git config --global user.email "JDoe@lbl.gov"
You can omit "--global" if you want this identity for ONLY the current repo.
Tracking 'origin'
-----------------
Unless you have done something unusual, the 'develop' branch in your clone from
BitBucket should automatically be tracking 'origin/develop' (and 'master' will
track 'origin/master'). The most basic command for tracking updates is "git
pull", BUT there are some risks that are associate with pull, as described in
detail at https://coderwall.com/p/jiswdq
To summarize: "git pull" will perform a merge which can generate undesired
non-linear history while "git pull --rebase" will flatten the desirable merge
commits which result from merging feature (or release) branches.
The alternative that avoids the risks is a two-step process:
$ git fetch
$ git rebase -p [origin/develop develop]
Where the arguments "origin/develop develop" are optional for git-1.8, but are
required with git-1.7.
This works like "git pull --rebase", but with the important addition of the
'-p' ('--preserve-merges') option to the rebase step to preserve the desired
branch structure.
Of course, if your local 'develop' branch has no un-pushed commits, then both
"git pull" and "git pull --rebase" are perfectly safe.
General Development
-------------------
We want to start every development task on a *distinct* branch off of
'develop'. These branches are called "feature branches", but are to be used
for bug fixes, documentation updates, and generally anything that is
"non-trivial".
When merging feature branches to develop, we want a (nearly) linear history,
but want to be able to clearly see the start and end of the sequence of commits
which correspond to any given feature branch. So, we want a "true merge" with
a commit which is a summary of the branch (bug fix, enhancement, etc.) which is
being merged. Therefore, we do NOT want a fast-forward but still require a
rebase prior to merging to keep a linear history. This gets clearer in the
examples below.
If one is using git-flow then the sequence for a feature branch "example" is:
[begin with an up-to-date 'develop']
$ git flow feature start example
[work on the branch until the task is done and tested]
$ git flow feature finish -r example
$ git push origin develop
The '-r' option to the finish forces a rebase to ensure a (nearly) linear
history if you have other commits/merges to 'develop' between the start and
finish of this feature branch.
If there is a merge conflict, resolve the conflict(s) and run "git commit" to
complete the merge. After that, there are two choices: you can simply reissue
the "finish" which should pick up where it left off, OR you can complete the
remaining step (branch deletion) using the non-git-flow steps, below.
It is worth noting that if the feature branch contains exactly one commit, then
git-flow will perform a fast-forward commit. This is under the assumption that
a single-commit branch is a "trivial" change, and is consistent with GASNet's
desired practice. HOWEVER, if you want to have a true merge you can use the
non-git-flow steps below even if you used git-flow to create the branch. If you
only want the opportunity to edit the commit message, that can always be done
using "git commit --amend" prior to the push.
To get the same behavior with plain git (without git-flow):
[begin with an up-to-date 'develop']
$ git checkout -b feature/example develop
[work on the branch until the task is done and tested]
$ git rebase develop feature/example
$ git checkout develop
$ git merge [--log] --edit --no-ff feature/example
$ git branch -d feature/example
$ git push origin develop
Some notes on the merge step:
--log Optionally seeds the commit message with the summary (first line) of
each of the constituent commits.
--edit Required so one can edit the commit message to write a description of
the work being merged.
The --edit flag to "git merge ..." doesn't exist in git-1.7, but it can be
simulated by using a two-step merge+commit:
$ git merge [--log] --no-commit --no-ff feature/example
$ git commit
which invokes the editor at the commit step.
So, what to do in case of a push failure above (race against a peer)?
If your post-merge "git push origin develop" fails with
! [rejected] develop -> develop (non-fast-forward)
then you should fetch and then rebase onto an up-to-date 'origin/develop':
$ git fetch
$ git rebase -p [origin/develop develop]
$ git push origin develop
Where the rebase arguments "origin/develop develop" are optional for git-1.8,
but are required with git-1.7. As described earlier, the "-p" is vital to
preserving the branch structure we are trying to achieve, and is the reason
that we should not use the more common "git pull --rebase".
One caveat here is that if you were to delay removing the feature branch until
after the (failed) push, you must use "-D" instead of "-d"
$ git branch -D feature/example
because the "rebase -p" results in git not realizing that your
branch has been fully merged. So, this is motivation to keep the push last.
Note that the fetch+rebase-p approach will preserve the branch structure even
if you have merged multiple feature branches to your local 'develop' since the
last fetch or pull. This is a good thing if you need to work disconnected for
an extended period.
Publishing Branches
-------------------
So far we've only worked with feature branches which are born, developed
and eventually merged to 'develop' in your own clone of the GASNet repo,
and thus live on a single machine. For a project like GASNet in
particular, it is seldom sufficient to develop and test on a single
platform. Additionally, collaboration is tough with the branch living in
your own clone of the repo. So, in this section we look at how to
"publish" your feature branch by making it appear on BitBucket along with
the standard 'develop' and 'master' branches. This means others can
collaborate with you on the work (perhaps just reviewing the work, but
potentially contributing to it as well), and you can easily clone your
feature branch to multiple machines where you can test.
If you're looking only for the ability to clone your branch, git does have
the ability (not described here) to use its ssh-based protocol to clone
your repos without using a hosting service like BitBucket. If you don't
want to work "in the open", but want the convenience of a hosted git, then
see the "Forking Development" section, below, for a more private
alternative to "publishing" of your feature branches
Publishing of a feature branch just means pushing it to the GASNet repo at
BitBucket and telling your local repo to consider that to be the "upstream"
for all push, pull and fetch operations. Assuming your branch has been
named "feature/pub-example" all it takes is one simple command:
$ git push -u origin feature/pub-example
If using git-flow, you save just two characters:
$ git flow feature publish pub-example
Note again that one can freely mix work with and without the git-flow
extensions. For instance the two commands above both work regardless of
whether or not "git flow feature start" was used to create the branch (so
long as one uses the "feature/" prefix consistently with plain git).
As with work committed to 'develop', your work exists only in your local
repository until you explicitly push it to BitBucket:
$ git push origin feature/pub-example
Or, potentially just "git push" depending on your configuration.
Regardless of whether one uses the git-flow or plain git steps to "finish"
the feature branch, there is one additional step which is needed at the
end to delete the branch on the BitBucket repo:
$ git push origin :feature/pub-example
+ Rebasing published branches
A friendly reminder: it is considered rude to rewrite history in public.
While we have configured the BitBucket repo to disallow rebases on the
'develop' and 'master' branches, there is no such control on the branches
you may choose to publish. If you rebase or amend any commits that have
been pushed to BitBucket there is no mechanism to stop you, and you *will*
cause problems for any repo which has pulled the effected commits. A very
simple rule is that if you need to pass "--force" (or "-f") to a "git push"
then you've done something "bad".
For a long-lived feature branch it is almost certain that one will need to
sync with 'develop' occasionally. At a minimum one should sync up at least
once near the end to test before the final merge to 'develop'. The
preferred work-flow for GASNet is a rebase-centric one, which would suggest
that one would want to perform syncs against 'develop' using rebase.
However, for a published branch a rebase would conflict with the
prohibition against public rewrites of history. There are at least three
ways one can resolve this apparent conflict.
1. Versioned branches:
The simplest way to deal with rebasing of a long-lived published feature
branch is to create (and publish) a new branch each time one wants to sync
with 'develop'. This means no disruption to anybody who has cloned the
prior branches, but does require communicating with your collaborators to
ensure a clean transition of development from one branch to the next. When
using this approach it is helpful to suffix the names of the new branches
with either a sequence number or the date of the rebase. Example:
$ git checkout -b feature/pub-example-2 feature/pub-example
$ git rebase develop
$ git push -u origin feature/pub-example-2
Of course you will want to delete all of these branches when the feature is
finally merged into 'develop', if not sooner than that.
2. Single branch:
If the idea of periodically shifting work to a new branch each time you
wish to rebase against 'develop' doesn't appeal to you, then you can keep a
single branch and use merges (and possibly cherry-picks) to sync your
feature branch with 'develop'. This means your branch's history may become
"ladder like", but all of that will go away in the final rebase when it is
time to merge back to 'develop'. For any commit from 'develop' that was
applied to your branch without conflict (whether by merge or cherry-pick)
git will be able to automatically skip the changes at rebase time.
3. Fork instead of branch:
If you are not looking to collaborate with others and really just want to
push your work to a public repo to simplify testing across multiple
platforms, then consider the next section "Forking Development" in which
you push your work somewhere NOT public. That way the entire "rewriting
history in public" issue goes away and you can "push -f" if you wish.
Forking Development
-------------------
The steps described above under "General Development" and "Publishing
Branches" both assume you have Write access to the GASNet repo on BitBucket.
The "Publishing Branches" section additionally assumes you want your
work-in-progress visible to the entire world. However, you can also create a
"fork" of the GASNet repo under your own account on BitBucket. This does not
require Write access to the GASNet repo and additionally allows you (as the
owner of the forked repo) to have full control over access permissions.
The concept of a "fork" is simply a hosted (could be any provider, not
necessarily BitBucket) clone of a repo (commonly called the "upstream" repo)
that is not pushed to its upstream.
In the case you are an "external" developer without Write access to the GASNet
repo, you can still contribute your work back to GASNet's 'develop' branch via
a "pull request" which uses all of git's considerable intelligence to merge
your changes with those which may have been pushed since you forked. The same
is true if you are a developer with Write access who has just chosen to work
in a private repo (though you can short-cut the pull request process
considerably). See more in "Pull Requests" below.
To create a fork from a given branch there are three steps:
1. Create an empty git repository with your hosting provider, and
set access permissions as you wish.
For the purpose of this example you are USER@bitbucket.org and
have created a repo named 'my-example-fork'.
2. Using either a new or existing clone of the GASNet repo, checkout
the branch you want to fork from.
This should almost always be 'develop'.
3. From within this checkout push a copy to your empty repo.
$ git push git@bitbucket.org:USER/my-example-fork HEAD:master
All you have done above is copy your HEAD (presumably the tip of GASNet's
'develop') to your own repo. This does not modify your clone of the GASNet
repo in any way (not even settings in .git/config).
At this point you can clone your new repo and work on it as a completely
independent project. However, if you wish to continue tracking GASNet's
'develop' there are (at least) two ways you can do it. One option is to add a
branch to your existing clone of the GASNet repo, while the other is to clone
your new repo and add a branch for tracking its upstream repo. Since the
first option begins in your existing clone (where you just ran "git push")
we'll look at that first.
+ Option 1: Fork as tracking branch
We need to create a "remote" to refer to the new repo, and a branch to track
it:
[ still in your clone of the GASNet repo ]
1. Create a remote to name the new repo and fetch its meta data:
$ git remote add USER/example git@bitbucket.org:USER/my-example-fork
$ git fetch USER/example
2. Create a branch to track 'master' in the new remote:
$ git branch -t feature/example-fork USER/example/master
3. Ensure push without a refspec sends your updates to the right place:
$ git config remote.USER/example.push feature/example-fork:master
The third step is unnecessary if you have push.default set to "upstream" in
your git configuration. However, that is a matter of preference and so the
third step appears here for completeness. If you do use this step and are
tracking multiple branches from the same repository, then you should create a
distinct "remote" for each or a "git push" will require a refspec argument to
do the "right thing".
Note that there is nothing special about the names "USER/example" (for the
remote) or "feature/example-fork" (for the branch). For instance, there is
no requirement to have a '/' in either name. The branch name was chosen to
match the git-flow convention for feature branches. This example would allow
a developer to work on the fork exactly as they would any other feature, with
the addition of having control over the access to the repo to which the branch
will be pushed.
+ Option 2: GASNet as upstream
The second option reverses the roles of the original and the fork, and may be
more appropriate for an external developer because their work is 'master' in
the forked repo. This option starts with cloning the fork, and then adds a
remote and branch for tracking the original repo:
[ starting in some location NOT in your clone of the GASNet repo ]
$ git clone git@bitbucket.org:USER/my-example-fork
$ cd my-example-fork
$ git remote add upstream https://bitbucket.org/berkeleylab/gasnet
$ git fetch upstream
$ git branch -t upstream upstream/develop
Again there is nothing special about the name "upstream" which has been used
for BOTH the remote and the branch, but their use is a common convention. It
is also worth noting that this example has used the anonymous https URL for
the definition of the "upstream" remote. This is appropriate for an external
developer without Write access to the repo.
Regardless of which of these two options you use, keep in mind that with the
default settings "git fetch" will only fetch the repository corresponding to
the current branch, while "git remote update" will fetch all remotes.
Pull Requests
-------------
+ Pulling your own work
If you are a developer with Write access to the GASNet git repo and have forked
to develop in private, then merging your fork back to 'develop' is as simple as
merging any other branch. If you followed the "Fork as tracking branch" steps
above, then you already have your fork setup (and named) just like any other
feature branch. So, you merge it the same way too (see "General Development",
above). Using the same names as in "Fork as tracking branch":
$ git rebase develop feature/example-fork
$ git checkout develop
$ git merge [--log] --edit --no-ff feature/example-fork
$ git push origin develop
If you are done with the fork, delete both the tracking branch and the remote:
$ git branch -d feature/example-fork
$ git remote rm USER/example
+ Preparing to generate a pull request
If you are an external developer (one without Write access) who has forked
GASNet, then when you are ready to contribute your work back to us the
preferred mechanism is known as a "pull request". Unlike sending patches
(which contain all of the changes but no history), a pull request involves
providing a GASNet developer with access to read your fork. This allow the
developer to incorporate not only your changes, but also your history (commit
messages). Before the pull request, you need to be sure of two things:
1. That your work meets the GASNet standards.
+ README-devel for GASNet's coding standards
+ Earlier sections of this doc for rules concerning git commit messages, etc.
2. That your fork will merge cleanly.
It needs to be rebased onto the branch it was forked from.
Since we use the git-flow model, we don't do three-way merges and only apply to
'develop' those changes that *could* be fast-forwarded, though we do a "true
merge" to allow a commit message for the merge. If you followed the steps
under "GASNet as upstream", above, then you already have an "upstream" branch
to track what you forked from. So, the steps to rebase are:
$ git checkout upstream
$ git pull
$ git rebase [-i] upstream master
If you think you may need (or just want) to cleanup your history, then the '-i'
option will cause an interactive rebase.
Finally, you need to do whatever your hosting service requires to ensure the
GASNet developers have access to clone your repository.
+ Generating a pull request
Now it is time for the pull request. If using BitBucket, then there is a GUI
for this, and you will find documentation on their site. If using another
hosting service, or if you just don't like the GUI, then you just need to
email the repo URL to us at gasnet-devel@lbl.gov with an explanation of the work
you are contributing back. Ideally you will have communicated and
collaborated with us prior to the pull request and we'll already be familiar
with the work.
+ Merging a pull request
Let's assume now that you are the GASNet developer who has been chosen to
merge the work of an external developer's pull request. You have the choice
between pulling into a feature branch or creating a temporary tracking
branch for the contributed fork. Unless you have high confidence that the
contribution requires little or no testing, the tracking branch approach is
recommended. First follow the steps under "Fork as a tracking branch", though
unless the contributor actually wants you pushing to their repo, you can skip
the "git config remote.<name>.push ..." step. Second, perform any/all
appropriate testing using the tracking branch prior to merging it to
'develop'. Finally, you can merge as described under "Pulling you own work".
When *not* using a tracking branch, the work required is actually not too
different. Instead of a "git merge ..." with the name of a branch, you will
"git pull ..." into a short-lived feature branch and merge that to 'develop'.
If using git-flow the steps are:
[ begin with an up-to-date 'develop' ]
$ git flow feature start pull-example
$ git pull URL [branch-if-not-the-default]
$ git rebase develop
[ carefully examine/test the resulting feature branch ]
$ git flow feature finish
$ git push origin develop
Without git-flow the equivalent steps are:
[begin with an up-to-date 'develop']
$ git checkout -b feature/pull-example develop
$ git pull URL [branch-if-not-the-default]
$ git rebase develop
[ carefully examine/test the resulting feature branch ]
$ git checkout develop
$ git merge [--log] --edit --no-ff feature/pull-example
$ git branch -d feature/pull-example
$ git push origin develop
Releases
--------
Even with Write access to the BitBucket repo, users don't have push rights to
'master' by default. If you need to produce releases, ask one of the
repository Admins to grant you push access.
For a release branch the steps using git-flow are much the same as for
development. For a hypothetical release of version 9.8.0:
[begin with an up-to-date 'develop' and 'master']
$ git flow release start 9.8.0
[prepare the release following the procedure in README-release]
$ git flow release finish -m "GASNet release 9.8.0" 9.8.0
$ git push --tags origin develop master
When using plain git commands there is just a minor difference because we don't
want to rebase onto 'develop' once the branch has started (because we
explicitly branched to keep concurrent changes on 'develop' from entering the
release). We do still want a non-fast-forward commit. The steps look like:
[begin with an up-to-date 'develop' AND 'master']
$ git checkout -b release/9.8.0 develop
[prepare the release following the procedure in README-release]
$ git checkout master
$ git merge --edit --no-ff release/9.8.0
$ git tag -a gasnet-9.8.0 -m "GASNet release 9.8.0" master
$ git checkout develop
$ git merge --edit --no-ff release/9.8.0
$ git branch -d release/9.8.0
$ git push --tags origin develop master
If using git-1.7 there is no support for "merge --edit"; see the text
regarding merging feature branches for the merge+commit alternative.
It may happen that while testing the release one finds that some feature on
'develop' is broken and must be excluded from the release. In that case a "git
revert" of the feature will be part of "[prepare the release...]". However,
this does not mean that the feature MUST be reverted on 'develop' as well. If
you *do* want it reverted on 'develop' then no extra actions are required
(though you should consider how you will resume work on the feature). If you
want to retain the feature on 'develop' then you must take care to exclude the
revert from what gets merged to 'develop'. While this is possible to do with
git-flow (by amending the merge commit prior to pushing), it is probably easier
to handle this situation using plain git, by reversing to revert on the release
branch between "checkout develop" and the merge that follows it.
Aliases
-------
There are a few examples in this document which require some non-default
options to git. The following are some suggested git aliases to help
reduce what one needs to remember (and type). See "git help config" for
information on creating git aliases.
+ "git pull-dev" and "git push-dev".
Matched pair to simplify syncing with origin/develop (esp. the fetch+rebase-p):
pull-dev = !git fetch origin develop && git rebase -p origin/develop develop
push-dev = push origin develop
+ "git mg <commit>"
To invoke merge with all of our desired options.
For git-1.8:
mg = merge --log --edit --no-ff
For git-1.7 (which lacks an --edit option to merge):
mg = !sh -c 'git merge --log --no-commit --no-ff "$@" && git commit' --
+ "git start <name>" and "git finish <name>"
These are simple (thus less powerful) alternatives to the corresponding
"git flow feature (start|finish)" commands:
start = !sh -c 'git checkout -b feature/$1 develop' --
finish = !sh -c 'git rebase develop feature/$1 && \
git checkout develop && \
git mg feature/$1 && \
git branch -d feature/$1' --
Note that "finish" requires "mg", defined above.
+ "git switch <name>"
In the same spirit as start and finish, this is a short-cut for checking
out a conventionally-named feature branch with less typing:
switch = !sh -c 'git checkout feature/$1' --
Proprietary (NDA) information
-----------------------------
[TODO: describe a detailed protocol]
At a VERY high-level:
+ Do NOT conduct NDA work using the BitBucket repository.
+ Work from a clone on a "controlled" machine.
+ Don't clone your repo containing NDA-covered to any "uncontrolled" machine.
+ Consider using "git archive" to move files w/o conveying any history or
deleted files.
+ Consider using "git archive" to import the final code (but no history or
deleted files) once it is allowable to do so.
--------------------------------------------------------------------------
The canonical version of this document is located here:
http://bitbucket.org/berkeleylab/gasnet/src/develop/README-git
For more information, please email: gasnet-devel@lbl.gov
or visit the GASNet home page at: http://gasnet.lbl.gov
--------------------------------------------------------------------------