Introduction
------------

These instructions are wrote to contributors who tend to send lots of
changes.  The basics from howto-contribute.txt file are assumed to be
read and understood by the time this file becomes useful.


Setup
-----

1. Find a git server that can be reached from anywhere in internet
anonymously.  Github is for example a popular choice.

2. Create your own util-linux contributor repository, and push an upstream
clone to there.

3. In these instructions the upstream remote repository is called
'origin' and the 'yourgit' is the contributor repo.

cd ~/projects
git clone git://git.kernel.org/pub/scm/utils/util-linux/util-linux.git
cd util-linux
git remote add yourgit git@github.com:yourlogin/util-linux.git
git push yourgit


Branches
--------

1. The name of your branch isn't crucial, but if you intend to contribute
regularly, it's beneficial to establish a naming convention that works well for
you. For instance, consider prefixing your branch name with the subsystem's
name, such as blkid, libmount, etc.

2. Avoid using the 'master' branch for your contributions. The 'master' branch
should be reserved for staying synchronized with the upstream repository.

3. Once you've completed your work, push your branch to your remote Git server.

git checkout master
git branch textual
# spent here most of the effort
git push yourgit textual:textual

5. Do not worry if you used stupid-and-wrong branch name, it can be fixed
before submission.

git branch -m stupid-and-wrong brilliant
git push yourgit brilliant:brilliant :stupid-and-wrong


Stay up to date
---------------

1. Ensure you have the latest from all remote repositories.

2. Merge upstream 'master' branch if needed to your local 'master'.

3. Rebase your working contribution branches.

4. Push the changes to 'yourgit'.

git fetch --all
git log --graph --decorate --pretty=oneline --abbrev-commit --all

5. If you notice upstream has changed while you were busy with your
changes rebase on top of the master, but before that:

6. Push a backup of your branch 'textual' to 'yourgit', then

git checkout master
git merge origin/master
git checkout textual
git rebase master

If rebase reports conflicts fix the conflicts.  In case the rebase
conflict is difficult to fix rebase --abort is good option, or recover
from 'yourgit', either way there is some serious re-work ahead with the
change set.

7. Assuming rebase went fine push the latest to 'yourgit'.

git push yourgit master:master
git push yourgit --force textual:textual

The contributor branch tends to need --force every now and then, don't be
afraid using it.

8. Push error with master branch

If 'master' needs --force then something is really messed up.  In that
case it is probably the wise to abandon(*) local clone, and start all
over from cloning upstream again.  Once the upstream is cloned add again
'yourgit' remote and

git push --mirror yourgit

But be WARNED.  The --mirror will nuke all of your stuff had in
'yourgit', that can cause data loss.  (*)So don't remove the local clone,
just move the directory to broken repos area.


Sending pull request
--------------------

1. When you are happy with your changes sleep over night.  This is not a
speed competition, and for some reason looking the changes the next day
often makes one to realize how things could be improved.  The best this
way you avoid changing the changes (that is always confusing).

2. Check the next day the changes compile without errors or warnings, and
that regression tests run fine.

make clean &&
make -j3 &&
make check

Notice that regression tests will not cover all possible cases, so you
most likely need to use the commands, features, and fixes you did
manually.

3. If you need to change something.

git rebase -i master
# change something
git push -f yourgit textual:textual

4. You have two ways how to send your pull request:

4.1 Github pull request (recommended)

This is recommended way for your changes. All you need is to press "pull
request" button on GitHub.

4.2. Send your work to the mailing list (optional)

Assuming the changes look good send them to mail list.  Yes, the all
of them!  Sending pull request with github is not visible for project
contributors, and they will not have change to review your changes.

Sending only the pull request, i.e., not each patch, to mail-list is also
bad.  Nothing is as good as seeing the changes as they are, and being
able to find them from with your favourite web search engine from
mail-list archive.  Obviously the pull request content does not get
indexed, and that is why it is worse.

git format-patch --cover-letter master..textual
git request-pull upstream/master https://github.com/yourlogin/util-linux.git textual > tempfile

Take from the 'tempfile' the header:

----------------------------------------------------------------
The following changes since commit 17bf9c1c39b4f35163ec5c443b8bbd5857386ddd:

  ipcrm: fix usage (2015-01-06 11:55:21 +0100)

are available in the git repository at:

  https://github.com/yourlogin/util-linux.git textual
----------------------------------------------------------------

and copy paste it to 0000-cover-letter.patch file somewhere near 'BLURB
HERE'.  Rest of the 'request-pull' output should be ignored.

In same go fix the Subject: line to have reasonable description, for
example

Subject: [PATCH 00/15] pull: various textual improvements


Feedback and resubmissions
--------------------------

1. Since you sent each patch to mail-list you can see which ones got to
be responded.  In case the feedback will result in changes to the
submission then rebase, perform the changes, and push again to your
remote.

# you probably should use 'Stay up to date' instructions now
git checkout textual
git rebase master -i
# edit something
git add files
git commit --amend
# Add 'Reviewed-by:', 'Tested-by:', 'Signed-off-by:', 'Reference:', and
# other lines near signoff when needed.  Attributing the reviewers is a
# virtue, try to do it.
git rebase --continue
git push -f yourgit textual:textual

2. Send a message to mail-list that the submitted change has changed, and
that the new version can be found from

https://github.com/yourlogin/util-linux/commit/0123456789abcdef0123456789abcdef01234567

3. There is no need to update the pull request cover letter.  The project
maintainer has done enough of this stuff to know what to do.


Repository maintenance
----------------------

1. When your remote branch is merged, or you got final reject, it is time
to clean it up.

git branch textual -d
git push yourgit :textual

2. If you have other contributor repositories configured you may also
want to clean up the branches the others are done with.

for I in $(git remote); do
  echo "pruning: $I"
  git remote prune $I
done

3. When all of your contributions are processed you should tidy up the
git's guts.

git reflog expire --all
git gc --aggressive --prune=now

Warning.  That tidying is not good idea while you are actively working
with the change set.  You never know when you need to recover something
from reflog, so keep that option available until you know the reflog is
not needed.


More branches, on top of branches, on top of ...
------------------------------------------------

Here is a one way of laying out multiple branches.

git log --graph --decorate --pretty=oneline --abbrev-commit --all
* 13bfff3 (HEAD, docs-update) docs: small improvements to howto-contribute.txt
* 5435d28 (sami/more, more) more: do not call fileno() for std{in,out,err} streams
* 3e1ac04 more: remove unnecessary braces
* c19f31c more: check open(3) return value
* 651ec1b more: move skipping forewards to a function from command()
* bf0c2a7 more: move skipping backwards to a function from command()
* 53a438d more: move editor execution to a function from command()
* b11628b more: move runtime usage output away from command()
* 6cab04e more: avoid long else segment in prbuf()
* a2d9fbb more: remove 'register' keywords
* c6b2d29 more: remove pointless functions
* b41fe34 more: remove function like preprocessor defines
* 1aaa1ce more: use paths.h to find bourne shell and vi editor
* 016a019 more: return is statement, not a function
* ff7019a more: remove dead code and useless comments
* 1705c76 more: add struct more_control and remove global variables
* 3ad4868 more: reorder includes, declarations, and global variables
* 7220e9d more: remove function declarations - BRANCH STATUS: WORK IN PROGRESS
* 04b9544 (sami/script) script: add noreturn function attributes
* e7b8d50 script: use gettime_monotonic() to get timing file timestamps
* 11289d2 script: use correct input type, move comment, and so on
* 524e3e7 script: replace strftime() workaround with CFLAGS = -Wno-format-y2k
* 0465e7f script: move do_io() content to small functions
* 751edca script: add 'Script started' line always to capture file
* f831657 script: remove io vs signal race
* eefc1b7 script: merge doinput() and output() functions to do_io()
* 9eba044 script: use poll() rather than select()
* a6f04ef script: use signalfd() to catch signals
* 4a86d9c script: add struct script_control and remove global variables
* d1cf19c script: remove function prototypes
* 6a7dce9 (sami/2015wk00) fsck.minix: fix segmentation fault
* 5e3bcf7 lslocks: fix type warning
* 3904423 maint: fix shadow declarations
* 17bf9c1 (upstream/master, sami/master, kzgh/master, master) ipcrm: fix usage
[...]

The above gives a hint to maintainer what is the preferred merge order.
The branches '2015wk00' and 'script' are ready to be merged, and they
were sent to mail-list.

The 'more' branch was not submitted at the time of writing this text.
Mark-up the branch is not ready is clearly marked in the commit subject,
that will need some rebaseing to before submission.

Good order of the branches is;

1. First the minor & safe changes.
2. Then the ready but less certain stuff.
3. Followed by work-in-progress.

If you go down this route you will get used to typing a lot of

git rebase previous-branch
git push -f yourgit branch:branch

Alternatively rebase each branch on top of origin/master, which is not
quite as good.  How do you ensure your own changes are not in conflict
with each other?  And there is no hint of preferred merging order.
