== Git quick start guide for Emacs Developers ==

Emacs uses Git as its version control system.

If you are an Emacs contributor without experience using Git in
particular and Distributed Version Control Systems (dVCS) in general,
this document tells you how to use Git in a simple, CVS-like way.

The "workflow" described in this document allows you to:

* Contribute to Emacs in a CVS-like way, including the use of VC-dir.
* Get conversant with the Git UI.
* Have a starting point for learning the full capabilities of Git.

There is a separate document, [[GitForEmacsDevs]], that describes
several slightly more complex, but also more flexible workflows that
take advantage of the Git's advanced features.  Such workflows are
particularly useful if you are frequently making substantial changes
to Emacs.  You are encouraged to use the workflows described there.

=== Conventions and basic info ===

* Whenever we need to refer to the Emacs repository on the GNU
  servers, we'll use URL_TO_UPSTREAM_MASTER. At the time of this
  writing, it is ##<membername>@git.sv.gnu.org:/srv/git/emacs.git##.

* ##git help /command/## is an easy way to get documentation about
    /command/. Use this for learning useful command line options.

=== Starting ===

We start by telling Git who you are. This is used for recording the
author of the commits.  You will need to run two commands, one to set
your name among humans and the other to set your email address:

: ##git config --global user.name "Your Name Here"##

: ##git config --global user.email "your@email.address.here"##

You should also run this command to turn on strict integrity checking:

: ##git config --global transfer.fsckObjects true##

(See the thread
[https://lists.gnu.org/archive/html/emacs-devel/2016-01/threads.html#01802
"Recommend these .gitconfig settings for git integrity."] for why.)

Next, you need to clone a copy of the Emacs repository:

* ##git clone URL_TO_UPSTREAM_MASTER##

This will take a couple of minutes even on a fast connection;
it downloads a few hundreds of megabytes of data.  It could
take 15 or even 30 minutes on slower connections.

=== Daily work ===

If you're using the command-line:

* ##git pull##
* Edit files
* ##git add new-file ...##
* ##git commit -a##  (This commits all the changes you made to any of the files.)
* ##git push##

(The ##git add## command is needed only if you added new files that
are not yet registered with Git.)

We recommend invoking ##git status## and ##git diff## to view the
changes which will be committed, before invoking ##git commit -a##.

You can also commit using VC-dir:

* ##M-x vc-dir RET##
* ##m## (Mark files to commit)
* ##v##
* Type log (##C-c C-a## to pull in ChangeLog(s))
* ##C-c C-c##

It is a good idea to review your commit after doing it, by means of the
##git show## command.  In particularly, make sure you got the log
message right and without mistakes.  This is because fixing a mistake
in the last local commit is easy.  (If you spot mistakes, the next section
explains how to fix them.)

To push your commits to the upstream Emacs repository on Savannah,
you will need to type the ##git push## command from the shell prompt,
even if you use VC, as VC doesn't yet support a push command.

Before pushing, we recommend examining what you are about to push,
because fixing mistakes before pushing is much easier (see the next
section). To do that, use the command ##git show origin/master..##
(note the 2 dots: they are important). If you only have one local commit
you want to push, just ##git show## is enough.

=== If you made a mistake ===

If you want to discard your changes to a single file, the command
##git checkout FILE## will overwrite the named FILE with its version
as of the last pull from upstream.

If you commit something by mistake, or forgot to commit a file, or want to
fix a stupid typo in the commit log message, all is not lost.  Be sure to catch
these problems before you ##git push##, then the error was not yet propagated
upstream, and you can easily fix it.

To fix the last commit log message, use ##git commit --amend##.
To re-do the commit from scratch, use ##git reset HEAD^## (which undoes
the commit, but leaves your local changes intact), then fix whatever
needs fixing, and commit again.

If you caught your mistake only after ##git push##, the only way to fix it is
to push another commit.  Try to avoid that, as log messages cannot be
fixed this way.

=== If pushing fails ===

Before pushing, not just the files you are committing but _all_
your local source files must be up to date with upstream. So if
somebody else pushes to upstream between your ##git pull## 
and the ##git push## commands, your push will be rejected. If
that happens, you'll need to resync with the upstream repository:

* ##git pull##
* Resolve conflicts, if any (see below)
* ##git push##

=== Dealing with conflicts ===

The ##git pull## command performs a merge between any local
changes you have and the changes pushed by others to the
upstream repository since your last pull. This merge could fail
due to conflicts between your changes and changes by others
in the same portions of the same files. The conflicts could be
in changes you have already committed locally, or in
uncommitted changes.

==== Conflicts in uncommitted changes ====

If the conflicts are in uncommitted changes, Git will say something
like this:

<pre>
error: Your local changes to the following files would be overwritten by merge:
        file1
Please, commit your changes or stash them before you can merge.
Aborting
</pre>

To fix this, commit the offending files with

* ##git commit file1 -m "Commit to allow pull from upstream."##,

and then issue ##git pull## again. Now you may have conflicts due
to local committed changes, described below.

Alternatively, you could use ##git stash save file1## to move
the uncommitted changes out of the tree, then ##git pull##
again, and finally ##git stash pop## to restore your uncommitted
changes. 

==== Conflicts in committed changes ====

For conflicts in changes committed locally, Git will say something
like this:

<pre>
CONFLICT (content): Merge conflict in file1
Automatic merge failed; fix conflicts and then commit the result.
</pre>

The conflicts discovered by Git are marked by conflict markers
similar to other VCSes. To fix this, visit the files with conflicts in
Emacs.  This turns on the smerge-mode which has special
commands for handling conflicts.  In addition, saving any file
whose conflicts were completely resolved (i.e., no conflict
markers remain in it) invokes the ##git add## command on
that file, which prepares the file for merging and committing.
Now review all the conflict markers and resolve the conflicts
by editing the relevant portions of the file.

When you are done with resolving all the conflicts in all the
files, commit them, either from the vc-dir buffer or by typing
##git commit## from the shell prompt.

=== Commit the entire changeset ===

With Git you shouldn't commit the changed files one at a time if
they belong to the same logical change. So, if you made a change
in some Lisp code and also modified the documentation to be
consistent with the change, please don't do:

* ##git commit lisp/foo.el##
* ##git commit doc/lispref/foo.texi##

but instead do

* ##git commit lisp/foo.el doc/lispref/foo.texi ##

or just

* ##git commit -a##

if you want to commit all the changed files.

This is very important because every commit creates a *changeset*,
which is a discrete step on the history of the code base.
A changeset should correspond to one well-defined purpose
which is completely achieved with the corresponding commit as,
for instance, "Fix bug #342" or "Implement feature Foo".

=== More branches ===

If you work on other branches besides /master/, just ##cd## into your
repository and

: ##git checkout branch_name##

=== Other commands ===

Git has ##status##, ##log##, ##annotate##,  etc. They do pretty
much what you would expect from CVS and Bazaar experience.

##git revert##, on the other hand, behaves a bit differently than you
might expect.  You may want to use ##git reset## instead. Read the
documentation for both to decide.

=== Use VC-Dir ===

VC-Dir works fine with this setup. It doesn't support all features of
more advanced Git setups, though.

=== That's it ===

You know enough to continue your Emacs hacking. Furthermore, you have
the initial elements for turning your current setup into a more
advanced setup once you learn enough to do so. You will not need to
download all the history from upstream again.


=== What you have, what you are missing ===

You have in your disk a copy of the entire repository as of the
last ##git pull##. Hence, Git does not need to contact
a server upstream for displaying logs, reverting edited files,
annotating, etc. This is useful for working off-line.

Git makes possible to commit changes off-line to your local history
and send them upstream in one batch. There are several options with
associated trade-offs for doing this, so read GitForEmacsDevs or ask
on the emacs-devel mailing list if you are interested on that
possibility.

Git allows you to work as if you had your own personal CVS branch
in your machine and communicate changes with other developers, not
only with upstream. What's considered "upstream" is just an agreement
among the developers who participate on the same project. That is the
essence of Distributed Version Control. Your current setup can be
easily adapted for this, but you need to master the necessary Git
concepts before embarking on that practices.

Git makes it very easy to create as many private branches as you
wish.

=== Further reading ===

GitForEmacsDevs
