Moxie
2015-11-23 67834872ddd5630b9c30c53c2972f5dcbf3dd5aa
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
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<!-- Begin Header -->
<title>Gitblit</title>
<meta charset="utf-8">
<meta name="ROBOTS" content="INDEX">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
        
<link rel="stylesheet" href="./bootstrap/css/bootstrap.css">
<link rel='shortcut icon' type='image/png' href='./gitblt-favicon.png' />
<link rel="stylesheet" href="./prettify/prettify.css" />
<!-- Google Plus Profile Page -->
<link rel="publisher" href="https://plus.google.com/114464678392593421684" />
<style type="text/css"> a.gpluspage { margin-top:3px;text-decoration: none; } </style>
 
<!-- Google Plus One -->
<link rel="canonical" href="http://gitblit.com" />
<script type="text/javascript" src="https://apis.google.com/js/plusone.js"></script>
<style type="text/css"> div.gplusone { margin-top:12px; } </style>
 
<script src="./prettify/prettify.js"></script>
<script src="./bootstrap/js/jquery.js"></script>
<script src="./bootstrap/js/bootstrap.min.js"></script>
</head>
<body onload='prettyPrint()'>        <!-- Navigation Bar -->
        <div class="navbar navbar-fixed-top">
            <div class="navbar-inner">
                <div class="container">
                      <a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
                        <span class="icon-bar"></span>
                        <span class="icon-bar"></span>
                        <span class="icon-bar"></span>
                      </a>
                      <a class="brand" href="./"><img src="./gitblt_25_white.png" alt="Gitblit"></img></a>
                    <div class="nav-collapse">
                        <ul class="nav">
                            <li class='dropdown'> <!-- Menu -->
<a class='dropdown-toggle' href='#' data-toggle='dropdown'>about<b class='caret'></b></a>
<ul class='dropdown-menu'>
<li><a href='index.html'>overview</a></li>
<li><a href='features.html'>features</a></li>
<li><a href='screenshots.html'>screenshots</a></li>
</ul></li> <!-- End Menu -->
<li class='dropdown'> <!-- Menu -->
<a class='dropdown-toggle' href='#' data-toggle='dropdown'>documentation<b class='caret'></b></a>
<ul class='dropdown-menu'>
<li class='dropdown-submenu'> <!-- Submenu -->
<a tabindex='-1' href='#'>Gitblit GO</a>
<ul class='dropdown-menu'>
<li><a href='setup_go.html'>setup GO</a></li>
<li><a href='upgrade_go.html'>upgrade GO</a></li>
</ul></li> <!-- End Submenu -->
<li class='divider'></li>
<li class='dropdown-submenu'> <!-- Submenu -->
<a tabindex='-1' href='#'>Gitblit WAR</a>
<ul class='dropdown-menu'>
<li><a href='setup_war.html'>setup WAR</a></li>
<li><a href='upgrade_war.html'>upgrade WAR</a></li>
</ul></li> <!-- End Submenu -->
<li class='divider'></li>
<li class='dropdown-submenu'> <!-- Submenu -->
<a tabindex='-1' href='#'>Server Configuration</a>
<ul class='dropdown-menu'>
<li><a href='administration.html'>administration</a></li>
<li><a href='setup_authentication.html'>authentication</a></li>
<li><a href='setup_hooks.html'>push hooks</a></li>
<li><a href='setup_lucene.html'>lucene indexing</a></li>
<li><a href='setup_proxy.html'>reverse proxies</a></li>
<li><a href='setup_clientmenus.html'>client app menus</a></li>
<li><a href='setup_bugtraq.html'>bugtraq</a></li>
<li><a href='setup_mirrors.html'>mirrors</a></li>
<li><a href='setup_scaling.html'>scaling</a></li>
<li><a href='setup_fail2ban.html'>fail2ban</a></li>
<li class='divider'></li>
<li><a href='setup_viewer.html'>Gitblit as a viewer</a></li>
</ul></li> <!-- End Submenu -->
<li class='divider'></li>
<li class='dropdown-submenu'> <!-- Submenu -->
<a tabindex='-1' href='#'>Client Usage</a>
<ul class='dropdown-menu'>
<li><a href='setup_transport_http.html'>using HTTP/HTTPS</a></li>
<li><a href='setup_transport_ssh.html'>using SSH</a></li>
<li><a href='eclipse_plugin.html'>using the Eclipse plugin</a></li>
</ul></li> <!-- End Submenu -->
<li class='divider'></li>
<li class='dropdown-submenu'> <!-- Submenu -->
<a tabindex='-1' href='#'>Tickets</a>
<ul class='dropdown-menu'>
<li><a href='tickets_overview.html'>overview</a></li>
<li><a href='tickets_using.html'>using</a></li>
<li><a href='tickets_barnum.html'>barnum</a></li>
<li><a href='tickets_setup.html'>setup</a></li>
<li><a href='tickets_replication.html'>replication & advanced administration</a></li>
</ul></li> <!-- End Submenu -->
<li class='divider'></li>
<li class='dropdown-submenu'> <!-- Submenu -->
<a tabindex='-1' href='#'>Plugins</a>
<ul class='dropdown-menu'>
<li><a href='plugins_overview.html'>overview</a></li>
<li><a href='plugins_extensions.html'>extension points</a></li>
</ul></li> <!-- End Submenu -->
<li class='divider'></li>
<li><a href='federation.html'>federation</a></li>
<li class='divider'></li>
<li><a href='properties.html'>settings</a></li>
<li><a href='faq.html'>faq</a></li>
<li class='divider'></li>
<li><a href='design.html'>design</a></li>
<li><a href='rpc.html'>rpc</a></li>
</ul></li> <!-- End Menu -->
<li class='dropdown'> <!-- Menu -->
<a class='dropdown-toggle' href='#' data-toggle='dropdown'>releases<b class='caret'></b></a>
<ul class='dropdown-menu'>
<li><a href='releasenotes.html'>release notes</a></li>
<li><a href='releases.html'>release history</a></li>
</ul></li> <!-- End Menu -->
<li class='dropdown'> <!-- Menu -->
<a class='dropdown-toggle' href='#' data-toggle='dropdown'>downloads<b class='caret'></b></a>
<ul class='dropdown-menu'>
<li><a href='http://dl.bintray.com/gitblit/releases/gitblit-1.7.1.zip'>Gitblit GO (Windows)</a></li>
<li><a href='http://dl.bintray.com/gitblit/releases/gitblit-1.7.1.tar.gz'>Gitblit GO (Linux/OSX)</a></li>
<li><a href='http://dl.bintray.com/gitblit/releases/gitblit-1.7.1.war'>Gitblit WAR</a></li>
<li class='divider'></li>
<li><a href='https://registry.hub.docker.com/u/jmoger/gitblit/'>Gitblit GO (Docker)</a></li>
<li class='divider'></li>
<li><a href='http://plugins.gitblit.com'>Plugins Registry</a></li>
<li class='divider'></li>
<li><a href='http://dl.bintray.com/gitblit/releases/manager-1.7.1.zip'>Gitblit Manager</a></li>
<li><a href='http://dl.bintray.com/gitblit/releases/fedclient-1.7.1.zip'>Federation Client</a></li>
<li class='divider'></li>
<li><a href='http://dl.bintray.com/gitblit/releases/gbapi-1.7.1.zip'>API Library</a></li>
<li class='divider'></li>
<li><a href='https://bintray.com/gitblit/releases/gitblit'>Bintray (1.4.0+)</a></li>
<li><a href='https://code.google.com/p/gitblit/downloads/list?can=1'>GoogleCode (pre-1.4.0)</a></li>
<li class='divider'></li>
<li><a href='http://gitblit.github.io/gitblit-maven'>Maven Repository</a></li>
</ul></li> <!-- End Menu -->
<li class='dropdown'> <!-- Menu -->
<a class='dropdown-toggle' href='#' data-toggle='dropdown'>links<b class='caret'></b></a>
<ul class='dropdown-menu'>
<li><a href='https://dev.gitblit.com'>dev.gitblit.com (self-hosted)</a></li>
<li class='divider'></li>
<li><a href='http://plugins.gitblit.com'>Plugins Registry</a></li>
<li class='divider'></li>
<li><a href='https://github.com/gitblit/gitblit'>Github</a></li>
<li><a href='https://github.com/gitblit/gitblit'>Issues</a></li>
<li><a href='http://groups.google.com/group/gitblit'>Discussion</a></li>
<li><a href='https://twitter.com/gitblit'>Twitter</a></li>
<li><a href='http://www.ohloh.net/p/gitblit'>Ohloh</a></li>
<li class='divider'></li>
<li><a href='https://vimeo.com/86164723'>Gitblit Tickets screencast</a></li>
<li><a href='https://asciinema.org/a/9342'>Gitblit SSH and Plugin Management asciicast</a></li>
<li><a href='http://episodes.gitminutes.com/2014/05/gitminutes-29-james-moger-on-gitblit.html'>GitMinutes #29: James Moger on Gitblit</a></li>
<li class='divider'></li>
<li><a href='https://twitter.com/JamesMoger'>@JamesMoger</a></li>
</ul></li> <!-- End Menu -->
<li class='divider-vertical'></li>
<li><a href='https://plus.google.com/114464678392593421684?prsrc=3' class='gpluspage'><img src='https://ssl.gstatic.com/images/icons/gplus-16.png' width='16' height='16 style='order: 0;'/></a></li><li><div class='gplusone'><g:plusone size='small' href='http://gitblit.com'></g:plusone></div></li>
                        </ul>
                    </div><!--/.nav-collapse -->
                </div>
            </div>
        </div><!-- end Navigation Bar -->
<div class='container'>
<!-- Begin Markdown -->
<h2 class="section" id='H1'><a href="#H1" class="sectionlink"><i class="icon-share-alt"> </i></a>Ticket Replication & Advanced Administration</h2><p><em>SINCE 1.4.0</em></p><p><strong>Ticket Replication</strong><br/>Gitblit does <em>not</em> provide a generic/universal replication mechanism that works across all persistence backends.</p><p><strong>Advanced Administration</strong><br/>Gitblit does <em>not</em> provide a generic/universal for advanced administration (i.e. manually tweaking ticket data) however each service does have a strategy for that case.</p>
<h3 class="section" id='H2'><a href="#H2" class="sectionlink"><i class="icon-share-alt"> </i></a>FileTicketService</h3>
<h4 class="section" id='H3'><a href="#H3" class="sectionlink"><i class="icon-share-alt"> </i></a>Ticket Replication</h4><p>Replication is not supported.</p>
<h4 class="section" id='H4'><a href="#H4" class="sectionlink"><i class="icon-share-alt"> </i></a>Advanced Administration</h4><p>Use your favorite text editor to <strong>carefully</strong> manipulate a ticket's journal file. I recommend using a JSON validation service to ensure your changes are valid JSON.</p><p>After you've done this, you will need to reset Gitblit's internal ticket cache and you may need to reindex the tickets, depending on your changes.</p>
<h3 class="section" id='H5'><a href="#H5" class="sectionlink"><i class="icon-share-alt"> </i></a>BranchTicketService</h3>
<h4 class="section" id='H6'><a href="#H6" class="sectionlink"><i class="icon-share-alt"> </i></a>Ticket Replication</h4><p>Gitblit supports ticket replication for a couple of scenarios with the <em>BranchTicketService</em>. This requires that the Gitblit instance receiving the ticket data be configured for the <em>BranchTicketService</em>. Likewise, the source of the ticket data must be a repository that has ticket data persisted using the <em>BranchTicketService</em>.</p>
<h5 class="section" id='H7'><a href="#H7" class="sectionlink"><i class="icon-share-alt"> </i></a>Manually Pushing refs/meta/gitblit/tickets</h5><p>Let's say you wanted to create a perfect clone of the Gitblit repository hosted at <a href="https://dev.gitblit.com">https://dev.gitblit.com</a> in your own Gitblit instance. We'll use this repository as an example because it is configured for the <em>BranchTicketService</em>.</p><p><strong>Assumptions</strong></p>
<ol>
  <li>We are pushing to our local Gitblit with the admin account, or some other privileged account</li>
  <li>Our local Gitblit is configured for create-on-push</li>
  <li>Our local Gitblit is configured for the <em>BranchTicketService</em></li>
</ol><p><strong>Procedure</strong></p>
<ol>
  <li>First we'll clone a mirror of the source repository:<pre>git clone --mirror <a href="https://dev.gitblit.com/r/gitblit.git">https://dev.gitblit.com/r/gitblit.git</a> </pre></li>
  <li>Then we'll add a remote for our local Gitblit instance:<pre>cd gitblit.git<br/>git remote add local <a href="https://localhost:8443/gitblit.git">https://localhost:8443/gitblit.git</a> </pre></li>
  <li>Then we'll push <em>everything</em> to our local Gitblit:<pre>git push --mirror local</pre></li>
</ol><p>If your push was successful you should have a new repository with the entire official Gitblit tickets data.</p>
<h5 class="section" id='H8'><a href="#H8" class="sectionlink"><i class="icon-share-alt"> </i></a>Mirroring refs/meta/gitblit/tickets</h5><p>Gitblit 1.4.0 introduces a mirroring service. This is not the same as the federation feature - although there are similarities.</p><p>If you setup a mirror of another Gitblit repository which uses the <em>BranchTicketService</em> <strong>AND</strong> your Gitblit instance is configured for <em>BranchTicketService</em>, then your Gitblit will automatically fetch and reindex all tickets without intervention or further configuration.</p><p><strong>Things to note about mirrors...</strong></p>
<ol>
  <li>You must set <em>git.enableMirroring=true</em> and optionally change <em>git.mirrorPeriod</em></li>
  <li>Mirrors are read-only. You can not push to a mirror. You can not manipulate a mirror's ticket data.</li>
  <li>Mirrors are a Git feature - not a Gitblit invention. To create one you must currently use Git within your <em>git.repositoriesFolder</em>, you must reset your cache, and you must trigger a ticket reindex.<pre>git clone --mirror &lt;url&gt;<br/>curl --insecure --user admin:admin "https://localhost:8443/rpc?req=clear_repository_cache"<br/>curl --insecure --user admin:admin "https://localhost:8443/rpc?req=reindex_tickets&amp;name=&lt;repo&gt;"</pre></li>
  <li>After you have indexed the repository, Gitblit will take over and incrementally update your tickets data on each fetch.</li>
</ol>
<h4 class="section" id='H9'><a href="#H9" class="sectionlink"><i class="icon-share-alt"> </i></a>Advanced Administration</h4><p>Repository owners or Gitblit administrators have the option of manually editing ticket data. To do this you must fetch and checkout the <code>refs/meta/gitblit/tickets</code> ref. This orphan branch is where ticket data is stored. You may then use a text editor to <strong>carefully</strong> manipulate journals and push your changes back upstream. I recommend using a JSON validation tool to ensure your changes are valid JSON.</p>
<pre><code>git fetch origin refs/meta/gitblit/tickets
git checkout -B tix FETCH_HEAD
...fix data...
git add .
git commit
git push origin HEAD:refs/meta/gitblit/tickets
</code></pre><p>Gitblit will identify the incoming <code>refs/meta/gitblit/tickets</code> ref update and will incrementally index the changed tickets OR, if the update is non-fast-forward, all tickets on that branch will be reindexed.</p>
<h3 class="section" id='H10'><a href="#H10" class="sectionlink"><i class="icon-share-alt"> </i></a>RedisTicketService</h3>
<h4 class="section" id='H11'><a href="#H11" class="sectionlink"><i class="icon-share-alt"> </i></a>Ticket Replication</h4><p>Redis is capable of sophisticated replication and clustering. I have not configured Redis replication myself. If this topic interests you please document your procedure and open a pull request to improve this section for others who may also be interested in Redis replication.</p>
<h4 class="section" id='H12'><a href="#H12" class="sectionlink"><i class="icon-share-alt"> </i></a>Advanced Administration</h4><p>You can directly manipulate the journals in Redis. The most convenient way do manipulate data is using the simple, but very competent, <a href="http://redisdesktop.com">RedisDesktopManager</a>. It even provides JSON pretty printing which faciliates editing.</p><p>After you've done this, you will need to reset Gitblit's internal ticket cache and you may need to reindex the tickets, depending on your changes.</p><p>The schema of the Redis backend looks like this <em>repository:object:id</em>.</p>
<pre><code>redis 127.0.0.1:6379&gt; keys *
1) &quot;~james/mytickets.git:ticket:8&quot;
2) &quot;~james/mytickets.git:journal:8&quot;
3) &quot;~james/mytickets.git:ticket:4&quot;
4) &quot;~james/mytickets.git:counter&quot;
5) &quot;~james/mytickets.git:journal:2&quot;
6) &quot;~james/mytickets.git:journal:4&quot;
7) &quot;~james/mytickets.git:journal:7&quot;
8) &quot;~james/mytickets.git:ticket:3&quot;
9) &quot;~james/mytickets.git:ticket:6&quot;
10) &quot;~james/mytickets.git:journal:1&quot;
11) &quot;~james/mytickets.git:ticket:2&quot;
12) &quot;~james/mytickets.git:journal:6&quot;
13) &quot;~james/mytickets.git:ticket:7&quot;
14) &quot;~james/mytickets.git:ticket:1&quot;
15) &quot;~james/mytickets.git:journal:3&quot;
</code></pre><p><strong>Some notes about the Redis backend</strong><br/>The <em>ticket</em> object keys are provided as a convenience for integration with other systems. Gitblit does not read those keys, but it does update them.</p><p>The <em>journal</em> object keys are the important ones. Gitblit maintains ticket change journals. The <em>journal</em> object keys are Redis LISTs where each list entry is a JSON change document.</p><p>The other important object key is the <em>counter</em> which is used to assign ticket ids.</p>
<h3 class="section" id='H13'><a href="#H13" class="sectionlink"><i class="icon-share-alt"> </i></a>Resetting the Tickets Cache and Reindexing Tickets</h3><p>Reindexing can be memory exhaustive. It obviously depends on the number of tickets you have. Normally, you won't need to manually reindex but if you do, offline reindexing is recommended.</p>
<h4 class="section" id='H14'><a href="#H14" class="sectionlink"><i class="icon-share-alt"> </i></a>Offline Reindexing</h4>
<h5 class="section" id='H15'><a href="#H15" class="sectionlink"><i class="icon-share-alt"> </i></a>Gitblit GO</h5><p>Gitblit GO ships with a script that executes the <em>com.gitblit.ReindexTickets</em> tool included in the Gitblit jar file. This tool will reindex <em>all</em> tickets in <em>all</em> repositories <strong>AND</strong> must be run when Gitblit is offline.</p>
<pre><code>reindex-tickets &lt;baseFolder&gt;
</code></pre>
<h5 class="section" id='H16'><a href="#H16" class="sectionlink"><i class="icon-share-alt"> </i></a>Gitblit WAR/Express</h5><p>Gitblit WAR/Express does not ship with anything other than the WAR, but you can still reindex tickets offline with a little extra effort.</p><p><em>Windows</em></p>
<pre><code>java -cp &quot;C:/path/to/WEB-INF/lib/*&quot; com.gitblit.ReindexTickets --baseFolder &lt;baseFolder&gt;
</code></pre><p><em>Linux/Unix/Mac OSX</em></p>
<pre><code>java -cp /path/to/WEB-INF/lib/* com.gitblit.ReindexTickets --baseFolder &lt;baseFolder&gt;
</code></pre>
<h4 class="section" id='H17'><a href="#H17" class="sectionlink"><i class="icon-share-alt"> </i></a>Live Reindexing</h4><p>You can trigger a live reindex of tickets for any backend using Gitblit's RPC interface and curl or your browser. This will also reset Gitblit's internal ticket cache. Use of this RPC requires <em>web.enableRpcServlet=true</em> and <em>web.enableRpcManagement=true</em> along with administrator credentials.</p>
<pre><code>curl --insecure --user admin:admin &quot;https://localhost:8443/rpc?req=reindex_tickets&quot;
curl --insecure --user admin:admin &quot;https://localhost:8443/rpc?req=reindex_tickets&amp;name=gitblit.git&quot;
</code></pre>
<h4 class="section" id='H18'><a href="#H18" class="sectionlink"><i class="icon-share-alt"> </i></a>Migrating Tickets between Ticket Services</h4>
<h5 class="section" id='H19'><a href="#H19" class="sectionlink"><i class="icon-share-alt"> </i></a>Gitblit GO</h5><p>Gitblit GO ships with a script that executes the <em>com.gitblit.MigrateTickets</em> tool included in the Gitblit jar file. This tool will migrate <em>all</em> tickets in <em>all</em> repositories <strong>AND</strong> must be run when Gitblit is offline.</p>
<pre><code>migrate-tickets &lt;outputservice&gt; &lt;baseFolder&gt;
</code></pre><p>For example, this would migrate tickets from the current ticket service configured in <code>c:\gitblit-data\gitblit.properties</code> to a Redis ticket service. The Redis service is configured in the same config file so you must be sure to properly setup all appropriate Redis settings.</p>
<pre><code>migrate-tickets com.gitblit.tickets.RedisTicketService c:\gitblit-data
</code></pre>
<h5 class="section" id='H20'><a href="#H20" class="sectionlink"><i class="icon-share-alt"> </i></a>Gitblit WAR</h5><p>Gitblit WAR does not ship with anything other than the WAR, but you can still migrate tickets offline with a little extra effort.</p><p><em>Windows</em></p>
<pre><code>java -cp &quot;C:/path/to/WEB-INF/lib/*&quot; com.gitblit.MigrateTickets &lt;outputservice&gt; --baseFolder &lt;baseFolder&gt;
</code></pre><p><em>Linux/Unix/Mac OSX</em></p>
<pre><code>java -cp /path/to/WEB-INF/lib/* com.gitblit.MigrateTickets &lt;outputservice&gt; --baseFolder &lt;baseFolder&gt;
</code></pre>
<!-- End Markdown -->
<div ><ul class="pager"><li class="previous"><a href="tickets_setup.html">&larr; setup</a></li> </ul></div><footer class="footer"><p class="pull-right">generated 2015-11-23</p>
<p>The content of this page is licensed under the <a href="http://creativecommons.org/licenses/by/3.0">Creative Commons Attribution 3.0 License</a>.</p>
</footer>
</div>
<!-- Google Analytics -->
<script type="text/javascript">
    var _gaq = _gaq || [];
    _gaq.push(['_setAccount', 'UA-24377072-1']);
    _gaq.push(['_trackPageview']);
 
    (function() {
        var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
        ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
        var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
    })();
</script>
 
</body>
</html>