Files
JIMRI/help/en/html/doc/Technical/GitFAQ.shtml
T
2026-06-17 14:00:51 +02:00

922 lines
44 KiB
Plaintext

<!DOCTYPE html>
<html lang="en">
<head>
<meta name="generator" content="HTML Tidy for HTML5 for Apple macOS version 5.8.0">
<title>JMRI: Git FAQ</title>
<meta name="author" content="Bob Jacobsen">
<meta name="keywords" content="JMRI technical code Git FAQ">
<!--#include virtual="/help/en/parts/Style.shtml" -->
<!-- FAQ-Head -->
<script type="text/javascript">
/*<![CDATA[*/document.documentElement.className="hasJS";/*]]>*/
</script>
<link rel="stylesheet" type="text/css" href="https://www.jmri.org/web/css/faq.css" media="screen"><!-- /FAQ-Head -->
</head>
<body>
<!--#include virtual="/help/en/parts/Header.shtml" -->
<div id="mBody">
<!--#include virtual="Sidebar.shtml" -->
<div id="mainContent">
<h1>JMRI Code: Git FAQ</h1>
<p>This is a list of Frequently Asked Questions for Git, particularly regarding how we use it
with JMRI.<br>
Click on a question to open the answer.</p>
<p>There's a <a href="getgitcode.shtml">separate JMRI Help page</a> on how to <a href=
"getgitcode.shtml">get the code with Git</a>.</p>
<p>See also the <a href="index.shtml">Technical index</a> for more information on maintaining
JMRI code.</p>
<p>See also the <a href="../../FAQ.shtml">JMRI general FAQ.</a></p>
<h2>Common User Topics</h2>
<dl class="faq">
<dt id="install" class="on">How do I install Git?</dt>
<dd>
Git is free software. Depending on your computer type and your preferences, there are
several ways to install it. There's more info in the Git community's <a href=
"https://git-scm.com/book/en/v2/Getting-Started-Installing-Git">Getting Started</a>
guide.
<ul>
<li>Get it from the <a href="https://git-scm.com/downloads" target="_blank">Git download
page</a>.
</li>
<li>It comes with the GitHub Desktop application, available from the <a href=
"https://desktop.github.com" target="_blank">Git desktop download page</a> (OS X and
Windows only).See <a href="githubdesktopintro.shtml">here for an intro.</a>
</li>
<li>On the Mac, it's included when you <a href=
"https://developer.apple.com/xcode/download/">install Xcode</a> ( requires Apple Developer ID to Sign in ).
</li>
<li>On Linux you can use your package installer, e.g. <code>sudo yum install git</code>
or <code>sudo apt-get install git</code>.</li>
</ul>
</dd>
<dt>Setting up a Git environment for JMRI Developers</dt>
<dd>
You can set your local repository to pull automatically from the JMRI master on GitHub
and push to your fork (also on GitHub):<br>
<a href="https://www.jmri.org/web/images/GitHubWorkflow.png"><img src="https://www.jmri.org/web/images/GitHubWorkflow.png"
height="25%" width="25%" alt="GitHub Work Flow"></a>
<p>That horizontal arrow is the "Pull Request" (and subsequent pull) that records
information about how things get into the repository.</p>
<p>The arrows are both operations (push, pull) and also definitions of <em>where</em> to
look e.g. a URL. Git can store shorthand for a URL, called a "remote". The default remote
is called "origin". You can have many remotes defined.</p>
<p>Via the git command line tool you do this with this command:</p>
<div class="wide">
<pre>
$ git remote set-url --push origin https://github.com/<em>username</em>/JMRI.git
</pre></div>
where <code>username</code> is your github user name. You can check the current status with
of the push and pull repositories with:
<div class="wide">
<pre>
$ git remote -v
origin https://github.com/JMRI/JMRI.git (fetch)
origin https://github.com/<em>username</em>/JMRI.git (push)
</pre></div>
<p>This says that, by default, fetches and pulls come from the main JMRI/JMRI repository. When
you push, on the other hand, it goes to your own repository.<br>
Once you have a copy of your changes on GitHub, it is easy to <a href=
"https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request"
>generate a Pull Request</a> (link to GitHub)</p>
<ul>
<li>In a browser, navigate to your repository on GitHub that has the changes you want
someone else to pull and</li>
<li>press the green compare icon <img src="https://www.jmri.org/web/images/GitHubPR1.png" alt=
"GitHub PR1">, then click on Create Pull Request.</li>
<li>After your pull request has been reviewed, it can be merged back in to the main
JMRI/JMRI repository. The JMRI developer who "pulls" your changes into the community
source needs to have access to an online repository that has your changes, which is why
you need to have a place on GitHub in the first place...</li>
</ul>
</dd>
<dt id="working">Working with Git</dt>
<dd>
<p>With SVN and CVS, you check out a "working directory" to make your changes in, work in
it for a while, and eventually commit all your changes back to the main repository.</p>
<p>Git works on a different idea. Instead of multiple working directories, you have a
single repository that's been "cloned" from the main repository. If you're making
individual little changes, you can work directly on the default "master" branch within
it. If not, see <a href="#branch">Using Branches</a>, below.</p>
<p>To understand Git, it is good to know about the various <em>places</em> in your local
git repository:</p>
<ul>
<li>The content from the "remote" repo, which lives under the <code>.git/</code> hidden
directory,</li>
<li>The "staging" area (also called "index" or "cache"), and</li>
<li>The named "branch" you are using, which lives in</li>
<li>The working tree.</li>
</ul>
<p>When you <em>clone</em> a git repo, you are creating a directory structure that holds
all of these items. Unless you tell it otherwise, the working tree starts off filled with
contents of the <em>master branch</em> of the repo you cloned - and the <em>staging
area</em> is empty. As you make changes to the files in the working tree, you need to
explicitly <em>add</em> them to the staging area. Git knows about these files, but they
aren't yet officially part of your local repo.</p>
<p>Once you have populated the staging area with of all the things you have changed, a
<em>commit</em> operation will, uhm, officially commit your changes to your repo's
<code>.git/</code> structure.</p>
<p>When you <em>pull</em> or <em>push</em>, you are telling Git to synchronize your
<code>.git/</code> content with that of the remote repo you originally cloned things
from.</p>
<h3>Getting Started</h3>
<p>The first step is to log in to GitHub and clone your own copy of the main JMRI repo. This
will give you a safe place to push and pull from without impacting others.</p>
<h4>Using Git from the command line</h4>
<ul>
<li>Clone the JMRI repo to your local system (or update it):
<pre style="font-family: monospace;">
$ git clone https://github.com/JMRI/JMRI.git
</pre>
<p>or</p>
<pre style="font-family: monospace;">
$ git fetch
</pre>
<p>then</p>
<div class="wide">
<pre style="font-family: monospace;">
$ git diff ...origin
$ git merge origin/master
Auto-merging ... files ...
CONFLICT (content): Merge conflict in <em>some_file</em>
Automatic merge failed; fix conflicts and then commit the result.
$ vi <em>some_file</em> # the file has the conflicts marked, edit to fix...
$ git add <em>some_file</em>
$ git commit -m "Merged master fixed conflict"
$ git merge origin/master
</pre></div>
<p>or</p>
<pre style="font-family: monospace;">
$ git pull https://github.com/JMRI/JMRI.git
</pre>
</li>
<li>Make your changes locally, test them, etc.
<pre style="font-family: monospace;">
$ git add <em>newfile</em>
$ git rm <em>oldfile</em>
$ git add .
$ git status
$ git fetch
$ git merge
</pre>
</li>
<li>Make your changes available to the community
<div class="wide">
<pre style="font-family: monospace;">
$ git commit -m <em>"commit message"</em> <em>filename</em>, <em>filename</em>
</pre></div>
<p>or</p>
<div class="wide">
<pre style="font-family: monospace;">
$ git commit -a -m <em>"commit message"</em>
</pre></div>
</li>
</ul>
<h4>Using GitHub Desktop application</h4>
<p>GitHub Desktop is a free application that can do many of the same things that the git
command-line tool does, but provides an interface that many people find easier and more
friendly.</p>
<p>For more on GitHub Desktop, please see our <a href="githubdesktopintro.shtml">page on
using GitHub Desktop</a>.</p>
<ul>
<li>Clone the JMRI repo to your local system by picking an item from the "Clone" tab in
the File -&gt; Clone repository... menu and clicking "Clone":<br>
<a href="images/GhDtCloneDialog.png"><img src="images/GhDtCloneDialog.png"
alt="GitHub Desktop PR dialog"></a>
</li>
<li>Check your GitHub URL in the "Remote" tab from the Repository -&gt; Repository
Settings menu as:<br>
<a href="images/GhDtRepoSetting.png"><img src="images/GhDtRepoSetting.png"
alt="GitHub Desktop Repo Setting"></a>
</li>
<li>Make your changes locally, test them, etc.<br>
When it all works, <em>commit</em> your edit to your local JMRI repository by
returning to the GitHub Desktop application, reviewing all changes noticed by the
program, enter a Summary [1] and Description [2] and finally clicking the Commit to
&lt;branch&gt; [3] button:<br>
<a href="images/GhDtWindow.png"><img src="images/GhDtWindow.png"
alt="GitHub Desktop Window"></a>
<p>After your Commit, a white dot will appear near the end of the line that looks
like a siding in a <em>track plan</em>. Click it to read the title. To see the files
changed at another point in time, click an older commit dot:<br>
<a href="images/GhDtWindowSeeCommit.png"><img src="images/GhDtWindowSeeCommit.png"
alt="GitHub Desktop Commit"></a></p>
<p>After a commit, your new edits are only added to your local copy of your branch.
To have them show up in a place other people can see them, either click the
<strong>Sync</strong> button at top right, choose Sync (Cmd-S) from the Repository
menu or make Github Desktop automatically sync after every commit by checking the
Automatically Sync after Committing menu item in the Edit menu:<br>
<a href="images/GhDtSyncSetting.png"><img src="images/GhDtSyncSetting.png"
alt="GitHub Desktop auto sync menu"></a></p>
</li>
<li>When you've worked on something in GhDt for a week or more, other people definitely
have worked on other parts of JMRI. To integrate these new data into your copy, click
the <strong>Update from JMRI/master</strong> button in the top left of the pane (or
choose "Pull" from the "Repository" menu).<br>
You will see an animation of a small branch symbol in a circle, moving from the
straight white line down to the line below it:<br>
<a href="images/GhDtUpdateFrom.png"><img src="images/GhDtUpdateFrom.png"
alt="GitHub Desktop Pull"></a>
<p>This tells you that new code has been copied to your repo, and in a few seconds
this new code is also copied to your computer, so you can view it or use it, unless
they've been working on the same lines of code (See Resolve a Merge Conflict,
below)</p>
</li>
<li>To make your changes available to the community click "Pull Request" (top right
button), enter a title and click "Create".<br>
<table>
<tr>
<td>
<a href="images/GhDtPRCreate.png"><img src="images/GhDtPRCreate.png"
alt="GitHub Desktop Create PR dialog"></a>
</td>
<td>The name of the PR button will change into <strong>#123</strong><br>
signaling you can't make another PR in this branch<br>
from here (but you can still commit extra edits to it):</td>
<td>
<a href="images/GhDtPRCreated.png"><img src="images/GhDtPRCreated.png"
alt="GitHub Desktop PR Created message"></a>
</td>
</tr>
</table>
<p>Normally, a PR is meant for the master branch of the _original_ repo, say
JMRI:master. You may pull your PR in your own remote repo, but only a couple of
people, the maintainers, can pull your edits into the "real" JMRI:master. Before they
do that, they study what you've written, maybe even pull it into their own repo to
test it before merging it for every other JMRI user to see.<br>
When your PR is pulled &amp; merged &amp; closed, the PR #123 name will disappear and you may
delete the branch safely.</p>
</li>
</ul>
</dd>
<dt id="branchexamples">Branch Examples</dt>
<dd>
<img src="images/git_branch_baseline.png" class="floatRight" alt="Branch Baseline"> The
figure to the right shows a couple examples of how we use branches in Git. The black line
going from left to right is the "master" branch. Each dot on it is a change that somebody
made on the master branch.
<p>At the left, the blue rectangle shows how a change can be made.</p>
<ul>
<li>Somebody created a new branch (the colored line)</li>
<li>That person made a change on their new branch (colored dot)</li>
<li>And then, through the PR process, that was merged back onto the master branch
(rightmost black dot).</li>
</ul>
<p>That basic process is used to make all the changes to the master branch, although for
simplicity we haven't shown all the details for all of them.</p>
<p>Sometimes, your development work can take a while. Maybe you do it in several phases,
making multiple commits. Before you're finally ready to merge it back into the common
code with via a Pull Request (PR), somebody else can make a change on the master branch.
The green path shows that case. The branch was created, development took some time, and
then a change was made to master (black dot on black line) before the green change was
merged back. The merge process in the green arrowhead took care of this. Generally, this
is straightforward, because most of the code doesn't change very often: If just a couple
changes have been made, they rarely overlap. This motivates our "merge often" philosophy.
<img src="images/git_branch_merge_master.png" class="floatRight" alt="Branch merge"></p>
<p>Sometimes development goes on for such a long time that people made changes to master
that matter to you. Perhaps they're new features or bug fixes that you'd like to have in
your own development branch. Or perhaps they're changes that conflict, and you'd like to
resolve those conflicts in your own work now, rather than waiting for later.</p>
<p>The 2nd diagram to the right has an example of this. After the programmer created the
blue branch for his own work, changes were made on both his branch (first three dots on
blue line) and on master (three dots on black line). Sometime after that 3rd change on
master, the developer decided to "git merge master" onto his branch, bringing all those
changes in via the black diagonal arrow. Both his changes and the changes to master are
now present in the blue branch he's working on.</p>
<p>Later, he decides to merge his work back onto master via the blue arrow in the
middle.</p>
<p>But at that point, he can still continue to work on his branch (next blue dot).
Perhaps he's fixing a bug that was found by a user once the work was merged to master. Or
perhaps he's just working more in the same direction. Either way, when he's ready, he can
merge again (right-most blue diagonal), or keep working on his branch (blue line running
off to right), or merge other people's work to his branch once it's merged (not
shown).</p>
<p>By doing your work on your own branch:</p>
<ul>
<li>You get control over when you want to merge in other people work. You can hold off
on that as long as you want, even distributing your own version if you want to.</li>
<li>At the same time, you can merge your work into the master branch shared by others
whenever it's ready, without disrupting your own work: Your branch is unchanged by
merging it with master.</li>
</ul>
More complicated diagrams are possible, with branches from branches to work
collaboratively, etc. You can see <a href="https://github.com/JMRI/JMRI/network">JMRI's
entire branch graph</a> on the GitHub site.
<p>The basic idea is important: By working on a branch in your repository, your work can
be kept a part of the overall JMRI effort instead of being isolated and unavailable.</p>
</dd>
<dt id="branch">Using Branches</dt>
<dd>
Always work on a named <em>branch</em>, never on the one named "master". Though you can
work directly on the default "master" branch, good "Git Hygiene" encourages you to create
a feature branch so you can work on it and never mess up your local copy of JMRI:master.
Branches in Git are easy and cheap to create and use; you can have multiple branches at
the same time, and switch between them as you work on different projects.
<p>We recommend that you name branches starting with your GitHub account name or initials
(for example, "abc") and something that suggests what you are working on:
<code>"abc-decoder-xml-change"</code>, <code>"abc-2015-09-14"</code>,
<code>"abc-next-cool-thing"</code>, and <code>"abc-patch-NNNN"</code> are all fine. That
way, we know it's you, and you can sort out the rest. Keep the name short & simple enough
to easily type (because people will sometimes have to), and limit it to letters, numbers
and use the "-" instead of spaces; that'll make it easier to work with.</p>
<ul>
<li>Using git:
<ul>
<li>To create a branch called "<em>branchname</em>", you do<br>
<pre style="font-family: monospace;">
git checkout -b <em>branchname</em>
</pre>
The "-b" says to create the branch. To switch to an existing branch, just leave out that
option:<br>
<pre style="font-family: monospace;">
git checkout <em>branchname</em>
</pre>To see all the current branches, do<br>
<pre style="font-family: monospace;">
git branch
</pre>
</li>
<li>If other people in the community make changes to the master branch, you can
keep your branch up to date by merging those changes in with your branch<br>
<pre style="font-family: monospace;">
git checkout <em>branchname</em>
git merge -m"merging in current contents of master" master
</pre>
(If you leave off the message option, you may be prompted to add one in an editor) If any
changes were picked up and merged in, you can then commit them to your branch:
<pre style="font-family: monospace;">
git commit -a
</pre>
</li>
<li>
<p>When you're done, merge your changes back into the common line of development
with<br></p>
<pre style="font-family: monospace;">
git checkout master
git merge -m"merging to master" <em>branchname</em>
git commit -a
</pre>
</li>
<li>You can then delete your branch (if you're finally done with it) with<br>
<pre style="font-family: monospace;">
git checkout master
git branch -d branchname
</pre>
</li>
</ul>
</li>
<li>Using GitHub Desktop:
<ul>
<li>Click the "Add a Branch (+)" button, provide a name for your new branch and
using the From: pop-up, select the branch from where you want to create the new
branch:<br>
<a href="images/GhDtNewBranch.png"><img src="images/GhDtNewBranch.png"
alt="GitHub Desktop Repo Setting"></a>
</li>
<li>To delete a branch, select it in the "Show Branches" pop-up menu, and then
select <strong>Delete "my-patch"</strong> from the Branch menu.<br>
You can't do that with the master branch, so don't work in that, always work in a
named branch.<br>
<a href="images/GhDtDeleteBranch.png"><img src="images/GhDtDeleteBranch.png"
alt="GitHub Desktop Repo Setting"></a>
</li>
</ul>
</li>
<li>You can opt to create and delete branches in Github web just as easily. More help
on <a href=
"https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-and-deleting-branches-within-your-repository">
Github Web Branching</a>.
</li>
</ul>
</dd>
<dt id="share">Sharing Branches</dt>
<dd>
One of the advantages of Git branches is that it's easy for people to share them. This
lets one person work with something that another has done, including editing and
improving it, without it having to be released to everybody.
<p>Say Arnie has developed something on the "arnie-great-tool" branch. Bill wants to try
to use it on his layout. The steps are:</p>
<ol>
<li>Arnie commits it to local repository, and then pushes it to his GitHub repository.
<pre style="font-family: monospace;">
git checkout arnie-great-tool
(work on changes)
git commit -m"Added support for the Frobnab 2000"
git push
</pre>
</li>
<li>Bill can then get that by pulling it from Arnie's repository.
<pre style="font-family: monospace;">
git remote add arnie https://github.com/arnie/JMRI.git
git fetch arnie arnie-great-tool
git checkout arnie-great-tool
</pre>where the 2nd part of the "remote add" is the URL for Arnie's repository, and you just have
to do that command once to define "arnie" as an alias you can use in "git fetch".
</li>
<li>Now Bill can work with that code, and even change it as needed. If he makes changes
that he wants Arnie to have, he does the same process in reverse:
<pre style="font-family: monospace;">
git commit -m"Fixed a bug in sternerstat handling"
git push
</pre>which commits the changes and pushes them up into Bill's repository on Github.
<p>Then Arnie can merge those changes into his own copy with:</p>
<pre style="font-family: monospace;">
git checkout arnie-great-tool
git pull https://github.com/bill/JMRI.git arnie-great-tool
</pre>
</li>
</ol>
</dd>
<dt id="resolve">Resolving a Merge Conflict</dt>
<dd>
It's not uncommon for two or more people to have ideas about the same part of the program
or the JMRI website, each making commits and PR's for parts of the same files. If they
were working on different lines of text or code in one file, GitHub knows how to combine
those changes into one updated file. You may have to check your proposal still works, as
someone might have deleted the anchor you were referring to etc. If GHDt discovers that a
change from one person was inserted into master, and you have prepared changes to the
same line, GitHub Desktop asks you to help decide what to do by displaying the following
Conflict screen (Note the orange dots next to one of the file names):<br>
<a href="images/GhDtConflictNote.png"><img src="images/GhDtConflictNote.png"
alt="GitHub Merge Conflict Note"></a>
<p>Click on that name and choose Show in Finder or Open with External Editor (GhDt itself
has no edit tools).<br>
To find the spot where the Conflict occurred, look for the <code>&lt;&lt;&lt; HEAD ====
&gt;&gt;&gt; master</code> markers that were inserted by GitHub:<br>
<a href="images/GhDtConfictmark.png"><img src="images/GhDtConfictmark.png"
alt="GitHub Merge Conflict marking in code"></a><br>
Choose which of both versions you wish to keep (or make some combination) and remove the
<code>&lt; === &gt;</code> lines!<br>
<a href="images/GhDtConflictFixed.png"><img src="images/GhDtConflictFixed.png"
alt="GitHub Merge Conflict solved in code"></a></p>
<p>This new proposal should still be Committed to JMRI, so give it a fitting title i.e.
"Solve conflict" and click Commit (and Sync). This extra commit will be added to your PR
and be part of your proposal the maintainers will see. You shouldn't keep merge conflict
lurking overnight, as the maintainers have no way to fix them for you and they will have
to ignore it till you solved it.</p>
</dd>
<dt id="ci-tests">Continuous Integration Tests</dt>
<dd>
The main JMRI repositories run a set of tests on every Pull Request (PR). This is called
Continuous Integration (CI), and is a time-proven method to keep code quality up.
<p>You can add this to your repositor(ies) so that each push will get automatically
tested.</p>
<p>The two CI test services are "Travis CI" and "GitHub":</p>
<ul>
<li>Travis CI runs on Linux. It first does a check for wrong line ends (see <a href=
"#lineends">later section</a>), then runs the complete set of JUnit tests, including
testing screen operations.
</li>
<li>GitHub runs multiple operating systems.</li>
</ul>
To add these to your own repository:
<ul>
<li>For Travis CI, go to the <a href="https://www.travis-ci.com">Travis CI web page</a> and
"Sign Up". Use your GitHub account and email. At the end of that process, it will ask
you which of your GitHub repositories to monitor; you can select both the "JMRI" and
"website" forks.
</li>
<li>GitHub is automatically available and working on personal forks.</li>
</ul>
From then on, pushing to your own repository will run the tests. You'll get an email when
the tests are complete, or you can check on the web.
</dd>
<dt id="lineends">Handling Line Ends</dt>
<dd>
Mac and Linux use a LF character at the end of each line; Windows uses the CRLF pair.
JMRI's text files are, by convention, stored in Git with LF line ends.
<p>It's very important that Windows users not accidentally convert a file to CRLF line
ends. When that happens, Git thinks that every line has been changed: Git can no longer
provide useful, granular history information about earlier changes to the file.</p>
<p>There is a ".gitattributes" file that tells (most) command-line Git implementations
how to handle this properly. Unfortunately, not all IDEs obey the directives in the file.
For example, to get NetBeans on Windows to handle line-ends properly, a specific plugin
must be installed. See the <a href="NetBeans.shtml#windows">NetBeans JMRI help page</a> for
specifics.</p>
<p>If a file with changed line-ends is accidentally committed and forwarded in a
pull-request (PR), the bad file in that PR will be detected during the Travis CI test and
the PI will <strong>not</strong> be accepted and merged. Further, the PR will be marked
with a "CRLF" label. Since the history has already been lost in this file, the CRLF label
reminds the maintainers that it's not sufficient to just change the line-ends back to LF,
commit and push: The history has been <u>lost</u>, and more complicated measures must be
taken.<br>
The two approaches are:</p>
<ol>
<li>Abandon the PR and underlying edits, delete the branch, and redo it right. If
you're working properly, with your changes in a separate branch, and committing small
changes, this is the recommended course of action.</li>
<li>Alternately, it's possible to use Git tools to remove the improper commit(s) from
the branch. This is much more complicated. Get one of the developers with Git expertise
to do it for you, and then send them cookies as a thank-you.</li>
</ol>
<p>Maintainers who encounter an updated PR with the CRLF label should check to see that
all the files in the PR do <u>not</u> show all lines changed. If they do, even if they
have the correct LF line ends, the PR should not be merged.</p>
<p>Many <a href="XmlEditors.shtml">XML Editors</a> have a Preference Setting for line
ends.<br>
For example, in Espresso check that Line Endings are set to <strong>Unix (LF)</strong>
before starting to edit any JMRI file:<br>
<a href="images/EspressoPrefsLF.png"><img src="images/EspressoPrefsLF.png"
alt="Espresso LF Preference setting"></a></p>
</dd>
<dt id="testPR">Testing a Pull Request</dt>
<dd>
<p>Pull requests are just a special case of a branch. If you want to test them before
merging them into master, you can bring them into your local repository and work with
them. <a href="images/GitHubPullPRLinks.png"><img src="images/GitHubPullPRLinks.png"
class="floatRight" alt="GitHub Web PR screen"></a></p>
<p>In some cases, GitHub Web makes specific instructions available right on the
pull-request itself. Look near the bottom of the discussion thread, in the last
information block. The nice thing about those is that they automatically have the right
branch names, etc, included.</p>
<p>Please note that, in some cases, these have a "Step 1" for looking at the pull request
locally, and a "Step 2" for merging it back. Please do not do that Step 2 request from
the command line, but instead use the web interface for doing the actual merge.</p>
<p>If no instructions are displayed, here's the sequence of things to do:</p>
<ul>
<li>Find the source repository and branch name. To do this, look at the top of the
branch request for a line that says:
<blockquote>
<u>user</u> wants to merge <u>3</u> commits into JMRI:master from
<u>user</u>:<u>branch</u>
</blockquote>
<a href="images/GitHubPRbranchInfo.png"><img src="images/GitHubPRbranchInfo.png"
alt="GitHub Web branch screen"></a>
</li>
<li>Next, pull that branch onto your own machine with the command:
<div class="wide">
<pre style="font-family: monospace;">
git fetch https://github.com/<u>user</u>/JMRI.git <u>branch</u>:<u>local-branch</u>
</pre></div>
where you have to replace each underlined value:
<ul>
<li>Change "user" to the correct GitHub user name</li>
<li>Change "branch" to the name of the branch in the pull request (it's OK if this
is e.g. master)</li>
<li>Change "local-branch" to what you want to call the branch on your own machine.
<em>This must not exist already</em>. Something like "me-user-branch" will remind
you of whose repository you pulled it from, while marking as subsequent changes as
yours if you later share it with somebody else. (It's recommended that people start
their branch names with their own name, which simplifies all sorts of
operations)</li>
</ul>
</li>
<li>The branch now exists in your machine, and you can just move to it:
<pre style="font-family: monospace;">
git checkout <u>local-branch</u>
</pre>then compile, test, etc. as you'd like. You can even commit and share changes if you'd like,
because this is now your own development branch: It started at the other person's, but it's now
your own.
</li>
</ul>
</dd>
<dt id="bisect">Using "git bisect" to find the cause of a bug</dt>
<dd>
If you have a reproducible problem that you think was introduced by a change to the code,
"git bisect" can help you track down the commit that caused it. It's very efficient at
tracking down repeating problems due to a single change.
<p>Let's say that you know <code>v4.9.1</code> does not have the problem, and commit
<code>23482341</code> (made up number) does. A narrow range is good, but don't spend any
time on it; git bisect does a binary search that's very efficient. Then you check out the
bad version:</p>
<pre style="font-family: monospace;">
git checkout 23482341
</pre>You start the bisect process:
<pre style="font-family: monospace;">
git bisect start
git bisect bad
git bisect good v4.9.1
</pre>
<p>I.e. set up your branch <u>with</u> the problem, start 'git bisect', tell it the problem is
visible here and now, then tell it where there's a good version to search through. Git will sort
out the possible revision path(s) where the problem can lie and devise an optimal search. Then it
will checkout some place in the middle and tell you "Bisecting: 6 revisions left to test after
this" or something like this.</p>
<p>Test that code:</p>
<pre style="font-family: monospace;">
ant clean tests
</pre>(and whatever you need to recreate). Once you know if it's good or bad, you say
<pre style="font-family: monospace;">
git bisect good
</pre>
<p>or</p>
<pre style="font-family: monospace;">
git bisect bad
</pre>and repeat. Git will do a good job of giving you the minimal number of tests to do, and in
the end will show you the commit that turned "good" into "bad" - not the PR, the single commit. You
can then look at the exact changes in that commit to see what went wrong.
<p>After "git bisect" is finished, end the process with</p>
<pre style="font-family: monospace;">
git bisect reset
</pre>to get back to where you started.
</dd>
<dt id="SFnetPatches">Handling a GitHub contributed file or SF.net Patch</dt>
<dd>
Sometimes people contribute files via the <a href=
"https://sourceforge.net/p/jmri/patches/">SF.net issue tracker</a> or a <a href=
"https://docs.github.com/en/issues/tracking-your-work-with-issues/about-issues"
>GitHub Issue</a>. This discussion talks about how to handle those.
<ol>
<li>In your local repository, create a branch to hold the patch:
<blockquote>
<code>git checkout -b patch-NNNN</code>
</blockquote>
where NNNN is the patch number.
</li>
<li>Merge in the changed code as needed.</li>
<li>Commit your changes:
<blockquote>
<code>git commit -m"Patch-NNNN plus the patch subject line (author name)"</code>
</blockquote>
</li>
<li>It's now in your repository on a branch of its own, where you can sanity test
things as usual.</li>
<li>When you are happy, push your local repo's committed content to your GitHub
repository (assuming the default configuration, where "push" goes to your own
repository on GitHub) with
<blockquote>
<code>git push origin patch-NNNN</code>
</blockquote>
</li>
<li>Go to your repository on GitHub and start the "pull request" process.</li>
<li>On the second screen, switch the branch being compared in your repository from
"<strong>master</strong>" to "<strong>patch-NNNN</strong>". Then the rest of the pull
request goes as before.</li>
<li>Eventually, a JMRI maintainer will handle the pull request and merge it, which will
put the patch changes on the master branch in the repository.</li>
<li>You can wait for the merge to the main repository, and then perform a
<blockquote>
<code>git pull</code>
</blockquote>
to update your local repository with this patch on the master branch. Or, if you need
them sooner, you can immediately merge these changes onto your local master via
<blockquote>
<code>git checkout master<br>
git merge patch-NNNN<br></code>
</blockquote>
</li>
</ol>
The advantage of this approach is that it lets you keep all your own work separate from
any patches you're handling. The patches are on different branches than your work, so
they don't overlap.
</dd>
</dl>
<h2>Less-Common Operations</h2>
<dl class="faq">
<dt id="migrateSVN">Migrating un-committed changes from a SVN checkout</dt>
<dd>
<p>As we migrated from SVN to Git in late 2015, you may still have edits based on old
code. If you have changes to the JMRI code in an existing SVN checkout that you wish to
commit to the current development version in Git, here's what we recommend:</p>
<ol>
<li>"Update" to the HEAD of SVN. You should be doing this routinely anyway, because
you'll need to do it before your changes can eventually be submitted. Do this now and
solve any problems.
<blockquote>
<code>$ svn update</code>
</blockquote>
</li>
<li>Check the status and save the output. Double check that no conflicts are showing.
<blockquote>
<code>$ svn status</code><br>
<br>
save a copy to reference later ...<br>
<br>
<code>$ svn status &gt; saved-status.txt</code>
</blockquote>
</li>
<li>Diff the sources and save the output.
<blockquote>
<code>$ svn diff &gt; patch.txt</code>
</blockquote>
</li>
<li>Clone a copy of the JMRI Git repository on your machine. (See the <a href=
"getgitcode.shtml">previous page</a> for detailed instructions.)
<blockquote>
<code>$ git clone https://github.com/JMRI/JMRI.git</code>
</blockquote>
</li>
<li>In your new Git repo clone, checkout the sources as they were when the code was
switched from SVN to Git:
<blockquote>
<code>$ git checkout tags/svn-30001</code>
</blockquote>
This sets your working copy to be exactly the same as the last contents of SVN, the
same as the base for the <code>svn diff</code> you took earlier.<br>
</li>
<li>Apply the changes you had made in SVN to the new Git tree
<blockquote>
<code>$ patch -p0 &lt; patch.txt</code>
</blockquote>
</li>
<li>If you had created any completely new files in the SVN working directory, i.e. ones
with "A" or "?" status:
<ul>
<li>Copy those files into the corresponding place in your Git checkout.</li>
<li>
<em>Add</em> them to the Git staging queue: To <code>git add (pathname)</code> on
each of them to tell Git about them
<blockquote>
<code>$ git add <em>pathname/to/new/file</em></code>
</blockquote>
</li>
</ul>
</li>
<li>Check the status to get a list of changes.
<blockquote>
<code>$ git status</code>
</blockquote>
You should see the same list of changed files as the "svn status" you ran
earlier.<br>
</li>
<li><code>git stash save</code>
</li>
<li><code>git checkout master</code>
</li>
<li><code>git stash pop</code><br>
<br>
Depending on how much progress has taken place in Git, this might show some conflicts.
If so, you have to resolve them here.</li>
</ol>
<p>Now you can start developing, without having lost anything.</p>
</dd>
<dt id="CVSCookies">Embedded CVS, RCS and SVN cookies</dt>
<dd>
<p>When JMRI was originally using CVS, we used lines like:<br>
<code># The next line is maintained by CVS, please don't change it<br>
# $Revision$</code><br>
as an additional way of tracking file versions. When we migrated to SVN, we kept those
lines in certain files, like decoder XML, properties files, etc, that users are likely to
edit and submit back for inclusion.</p>
<p>But with Git, there's less need for these. So we'll be removing these lines as time
allows. If you're working on a file and happen to see one, usually in the header, you can
just delete it (if it has somebody's name, you might want to add that to the copyright
notice if there is one.)</p>
</dd>
</dl>
<!--#include virtual="/help/en/parts/Footer.shtml" -->
</div>
<!-- closes #mainContent-->
</div>
<!-- closes #mBody-->
<!-- FAQ-Tail -->
<script type="text/javascript" src="https://www.jmri.org/web/js/faq.js"></script><!-- /FAQ-Tail -->
<script src="/js/help.js"></script>
</body>
</html>