code:
The development of git-annex was made possible by the generous
donations of many people. I want to say "Thank You!" to each of
you individually, but until I meet all 1500 of you, this page will have to
do. You have my most sincere thanks. --[[Joey]]

(If I got your name wrong, or you don't want it publically posted here,
email <joey@kitenet.net>.)

## 2013-2014

Continued git-annex development was [crowd funded](https://campaign.joeyh.name/)
by these excellent people. *Hug*

Eric Hanchrow, Michael Barabanov, Douglas Butts, Cody Woodard, Anna Hess,
Maggie Hess, Francois Marier, Michael Linksvayer, Alexander Brem, Yaroslav
Halchenko, Otavio Real Salvador, Giovanni Moretti, Mark Hepburn, Jim
Cheetham, Ali Gündüz, Chia Shee Liang, Vincent Arel-Bundock, Mark R Jones,
Willard Korfhage, Faidon Liambotis, Daniel Callahan, Sheila Miguez,
Christopher Webber, Daniel Patterson, Charity Hanif, Blair Mckenzie, Romain
Lenglet, Joseph Liu, Robert Beaty, Remy van Elst, Juho Snellman, Jason
Davidson, Dane Larsen, Kuno Woudt, Navishkar Rao, Ryan Sorensen, Jonathan
Castello, Nimrod Mesika, Amitai Schlair, Zellyn Hunter, Jan Pieper, Boyd
Smith, Brett Eisenberg, Péter Károly Juhász, Allan Franta, Aaron De Vries,
Donald Plummer, Joona Lehtomäki, Evan Anderson, Pedro Côrte-Real, Bradley
Unterrheiner, Wietse van Buitenen, James Shubin, Daniel de Kok, Michael
Zehrer, Peter deHaan, David Schmitt, Ian Downes, Gioele Barabucci, Gergely
Nagy, Diego Ongaro, Jonas Wiklund, Strakhov Artem, £ukasz Szczęsny, Peter
Olson, Thomas Berker, Greg Young, narf, Michael Jakl, Andrea Rota, Tobias
Nix, Andreas Olsson, Tobias Ussing, Pere Quintana Segui, Pierre Gambarotto,
Yuriy Zaytsev, Thomas Djärv, Thomas Hochstein, Simon Lundmark, Damien
Diederen, Arthur Lutz, Gert Van Gool, Jed Brown, Sören Brunk, Thorsten
Bormer, Vincent Sanders, Thomas Lundstrøm, Robert Connolly, Marc Seeger,
Per Andreas Buer, Thomas Andersen, Hendrik Müller Hofstede, Dominik
Wagenknecht, Robert Walker, Nicholas Weigand, Maximilian Weigand, Thomas
Jost, John, Angel Ramboi, Thomas Bartels, Fernando Jimenez, Tobias
Mersmann, András Veres-Szentkirályi, Richard Hartmann, John Hedges,
Nedialko Andreev, Roderik Koenders, Sławomir Gwizdowski, Aapo Laitinen,
Jonathan Harrington, Dirk Kraft, Fabian Bartschke, Philip Frank, Patrick
Steegstra, Roberto Zedda, Leon Major, Torbjørn Thorsen, Lukas Anzinger,
Pollan Ruben, Daniel Hofer, Johannes Krampf, Jörn Gersdorf, Kristoffer Egil
Bonarjee, David Iwanowitsch, Daniel Egger, Titus Stahl, Robin Sheat, Thomas
Nicolaisen, Karsten Heymann, Askings & Medina Business Services, Pieter
Mulder, Geoffrey Huntley, Wouter Mooij, Kari Oikarinen, sven dowideit,
Ethan Aubin, Nathan Rickerby, Tobias Brunner, Stian Haukaas Eikeland, Jan
Dittberner, Jeffrey Goeke-Smith, Joseph Cullen, James Orr, Markus Plangg,
Glendon Solsberry, Georg Bauer, Andreas Leha, Ian Kozhurin, Boris Hupkens
van der Elst, Daniel Brockman, Scott Robinson, Olaf Lorenzen, Øyvind
Andersen Holm, Logan Owen, Christopher Douglass, Nicolas Pouillard, Florian
Schlegel, Hans-Christian Jehg, Thomas Mechtler, Joshua McKinney, Tom
Atkins, Paul Scott-Wilson, Rafal Czlonka, Benjamin Williams, Ulises Vitulli, Mesar
Hameed, Vishakh Vishakh, Daniel Washburn, Maximilian Haack, Jan Gondol,
Carlo Matteo Capocasa, Jevgenijs Zolotarskis, John Cooper, Matthew Gregg,
Peter Jarosak, Edward Heil, Kyle Kurtenbach, David Kaminski, Joonathan
Mägi, Piotr Ożarowski, Ernest Braganza, Adam Sjøgren, Simon Michael,
Protonet, Valentin Churavy, Trenton Cronholm, Ellis Whitehead, Maarten
Everts, Paul Tötterman, Julien Lefrique, Robert F Donnelly,
LeastAuthority.com, Floris Bruynooghe, Kevin Krouse, Bernhard Schmidt,
Jason Woofenden, Jacek Nykis, Benjamin Carrillo, Teemu Hukkanen, William
Heinbockel, Kristofer Bergstrom, Richard Gibson, Julian Andres Klode,
Jeffrey Guenthner, Jochen Kupperschmidt, Andrew Eskridge, Eric Wallmander,
Aaron Haviland, Evan Deaubl, Felix Crux, Matthew Marshall, Hamish Coleman,
xymostech, Matthew Mercer, Ben Challenor, András Csáki, Stelian Iancu,
Dmitri Popov, Anthony DiSanti, Perttu Luukko, Daniel Glassey, Aurélien
Pinceaux, Svenne Krap, Sven Hartge, Frank Blendinger, Lisa Feilen, Kyle
Kujala-Korpela, Walter Somerville, Filippo Giunchedi, Tyler Willingham,
Gernot Schulz, Daniel Gervais, Denver Gingerich, Nicolas Joseph, tommy,
bak, Grejdi G, Gabriel de Perthuis, Mayank Jain, Radu Raduta, Gregory
Grossmeier, Errol Hess, Janin Kolenc, Sean Whitton, Philippe Gauthier,
Ananda Widyadharma, Jochen Bartl, Fredrik Hammar, THM Schoemaker, Marek
Jawurek, Johan Herland, Gian-Maria Daffre, Justine Lam, Ori Livneh, Arnaud
Berthomier, Chad Horohoe, Lois DeFiore, Lieven Baes, Patrick Wheeler, James
Kim, Carlos Trijueque Albarran, Ritesh Nadhani, chesty, Andre Pereira,
Eskild Hustvedt, David Wagner, Maximiliano Curia, András Széll, Allan
Holman, Thomas Langewouters, Anonymous, Peter Daengeli, Josh Taylor, Abhishek Dasgupta, Maarten Aertsen, Mark Sheppard,
Daengeli, Josh Taylor, Abhishek Dasgupta, Maarten Aertsen, Mark Sheppard,
Markus Engström, Samuel Tardieu, Geog Wechslberger, Abdó Roig, Dmitry
Markushevich, Sergio Rubio, Jim Paris, Vivek Gani, Brock Spratlen, Nathan
Howell, Alan Chan, Alexandre Dupas, Daniel Atlas, Patrick Hallen, Matthew
Forrester, Binyamin Cherniavsky, Florent Fourcot, Nathan Yergler, Hannibal
Skorepa, Cedric Staub, Melissa Binde, Marc Bobillier, Zoran Zaric, Ralph
Mayer, Jay Pozo, Walter Somerville, Remy Honig, Bernhard Urban, Nurullah
Akkaya, Ari Pollak, Kalle Svensson, Stephan Schulz, Joshua Honeycutt,
Justin Keyes, Filias Heidt, Manish Sharma, Benoît Zugmeyer, Andrew Kraut,
Markus Breitenberger, Dominik Deobald, Aren Olson, Tobias Ammann, Peter
Lloyd, Pierre Chambart, Michael Alan Dorman, Kyle Meyer, Kristoffer
Gronlund, Jay Dugger, Jeff McNeill, Oskari Timperi, Mathias Linden,
Ole-Morten Duesund, Tom Lowenthal, Anders Lannerback, Tony Cantor,
Stephanie Eikenberry, Vanja Cvelbar, Fabrice Rossi, Franz Pletz, Karl
Wiberg, Sam Kleinman, Vincent Demeester, Tristan Helmich, Zero Art Radio,
Bruno Bigras, Ævar Arnfjörð Bjarmason, Stanley Yamane, Christopher Browne,
David Whittington, Fredrik Gustafsson, Peter Hogg, Tom Francart, Wouter
Verhelst, Christian Savard, wundersolutions, Andreas Fuchs, Eric Kidd,
Georg Lehner, Berin Martini, Stewart Wright, Bence Albertini, Stefan
Schmitt, Antoine Boegli, jscit, Christopher Kernahan, A Marshall, Jürgen
Peters, Aaron Whitehouse, Jouni K Seppanen, Michael Albertson, Andreas
Laas, Thomas Herok, Aurelien Gazagne, Bryan W Stitt, anonymous, Chris
Kastorff, Henning Hasemann, Leonardo Taglialegne, Frank Thomas, Frédéric
Schütz, Riad Wahby, Maxwell Swadling, Bram Senders, Péter Párkányi, Tom
Dimiduk, Christian Kellermann, Kilian Evang, Christian Studer, Tim
Humphrey, Jürgen, Richard Collins, Renaud Casenave-Péré, Patrick Lynn,
Gregor Gramlich, Hugo Mougard, Arun Srinivasan, Paul Tagliamonte, Don
Armstrong, Adam DeWitt, Timothy Hobbs, Jacob Briggs, Mark Eichin, Matthew
Raso-Barnett, Damien Raude-Morvan, Mark Lopez, Mattias Olsson, Marco A L
Barbosa, Thomas de Ruiter, Anders Claesson, Philipp Meier, Henrik Ahlgren,
Michael Hofmann, Audric SCHILTKNECHT, Wojtek Burakiewicz, Christian
Dietrich, Jacob Kirkwood, Fabian Jansen, gregor herrmann, Martin Werner,
Adam Baxter, Sören Köpping, Pierce Lopez, David Lehn, Michal Politowski,
John Lawrence, Nicholas Golder, Adam Spiers, Pär Mattsson, Matt Lee,
Timo Heister, Asbjørn Sloth Tønnesen, James Valleroy, Felix Gruber, Björn
Pettersson, Nicola Chiapolini, Christer Stenbrenden, Hannes Maier-Flaig,
Paul Walker, Cary Kempston, Andrew Cant, Albert Drengg,
Martin Pollow, Karl-Georg Sommer, Francois Cocquemas, Daniel Bross, Martin
Florian, Grigorios Prasinos, Olivier Berger, Andreas Herten, Kyle MacLea,
Sozykin Mikhail, André Klärner, Pascal VITOUX, Gunilla Johansson, Dara
Adib, Nicolas Bonifas, Glen Ogilvie, TasLUG, Shaun Westmacott, Georgi
Valkov, Nicolas Dietrich, Auroch, Rasmus Pank Roulund, Michael Niewiera,
Benjamin Koch, Joe Bogner, Christoph Varga, Florian Eitel, Tobias Braun,
Jochen Schulz, Diggory Hardy, Stephane Barland, Sebastian Bober, Arash
Rouhani-Kalleh, Geoffrey Irving, Hans Tzou, Mark Booth, Christoph Neckel,
Aleksandar Iliev, Baldur Kristinsson, Adam Colton, KAWACHI TAKASHI, Michal
Sojka, Alexander Brandstedt, Jarno Elonen, Rob Sharp, John Pybus, Antonino
Mazzurco, Damon Haley, Jason Locklin, ULRICH KORTENKAMP, Karthik
Poobalasubramanian, Alexandre Garel, David Clark, Jeff Johnson,
Mica Semrick, Paul Staab, Rémi Vanicat, Martin Holtschneider, Jan Ivar
Beddari, Peter Simons, Thomas Koch, Justin Geibel, Guillaume DELVIT, Shanti
Bouchez, Oliver Brandt, François Deppierraz, Chad Walstrom, Tim Mattison,
Jakub Antoni Tyszko, Casa do Boneco, Florian Tham,
and 30 anonymous bitcoin users

With an especial thanks to the WikiMedia foundation,
and Rede Mocambos.

## 2012-2013

<a name="kickstarter">
The git-annex assistant was [crowd funded on Kickstarter](http://www.kickstarter.com/projects/joeyh/git-annex-assistant-like-dropbox-but-with-your-own/).

### Major Backers

These people are just inspiring in their enthusiasm and generosity to this
project.

* Jason Scott
* strager

### Beta Testers

Whole weeks of my time were made possible thanks to each of these
people, and their testing is invaluable to the development of
the git-annex assistant.

* Jimmy Tang
* David Pollak
* Pater
* Francois Marier
* Paul Sherwood
* Fred Epma
* Robert Ristroph
* Josh Triplett
* David Haslem
* AJ Ashton
* Svenne Krap
* Drew Hess
* Peter van Westen

### Prioritizers

These forward-thinking people contributed generously just to help
set my priorities in which parts of the git-annex assistant were most
important to develop.

Paul C. Bryan, Paul Tötterman, Don Marti, Dean Thompson, Djoume, David Johnston
Asokan Pichai, Anders Østhus, Dominik Wagenknecht, Charlie Fox, Yazz D. Atlas,
fenchel, Erik Penninga, Richard Hartmann, Graham, Stan Yamane, Ben Skelton,
Ian McEwen, asc, Paul Tagliamonte, Sherif Abouseda, Igor Támara, Anne Wind,
Mesar Hameed, Brandur K. Holm Petersen, Takahiro Inoue, Kai Hendry,
Stephen Youndt, Lee Roberson, Ben Strawbridge, Andrew Greenberg, Alfred Adams
Andrew, Aaron De Vries, Monti Knazze, Jorge Canseco, Hamish, Mark Eichin,
Sherif Abouseda, Ben Strawbridge, chee rabbits, Pedro Côrte-Real

And special thanks to Kevin McKenzie, who also gave me a login to a Mac OSX
machine, which has proven invaluable, Jimmy Tang who has helped
with Mac OSX autobuilding and packaging, and Yury V. Zaytsev who
provides the Windows autobuilder.

### Other Backers

Most of the success of the Kickstarter is thanks to these folks. Some of
them spent significant amounts of money in the guise of getting some
swag. For others, being listed here, and being crucial to making the
git-annex assistant happen was reward enough. Large or small, these
contributions were, literally, my bread and butter this year.

Amitai Schlair, mvime, Romain Lenglet, James Petts, Jouni Uuksulainen,
Wichert Akkerman, Robert Bellus, Kasper Souren, rob, Michiel Buddingh',
Kevin, Rob Avina, Alon Levy, Vikash, Michael Alan Dorman, Harley Pig,
Andreas Olsson, Pietpiet, Christine Spang, Liz Young, Oleg Kosorukov,
Allard Hoeve, Valentin Haenel, Joost Baaij, Nathan Yergler, Nathan Howell,
Frédéric Schütz, Matti Eskelinen, Neil McGovern, Lane Lillquist, db48x,
Stuart Prescott, Mark Matienzo, KarlTheGood, leonm, Drew Slininger,
Andreas Fuchs, Conrad Parker, Johannes Engelke, Battlegarden, Justin Kelly,
Robin Wagner, Thad Ward, crenquis, Trudy Goold, Mike Cochrane, Adam Venturella,
Russell Foo, furankupan, Giorgio Occhioni, andy, mind, Mike Linksvayer,
Stefan Strahl, Jelmer Vernooij, Markus Fix, David Hicks, Justin Azoff,
Iain Nicol, Bob Ippolito, Thomas Lundstrøm, Jason Mandel, federico2,
Edd Cochran, Jose Ortega, Emmett Agnew, Rudy Garcia, Kodi, Nick Rusnov,
Michael Rubin, Tom de Grunt, Richard Murray, Peter, Suzanne Pierce, Jared
Marcotte, folk, Eamon, Jeff Richards, Leo Sutedja, dann frazier, Mikkel
kristiansen, Matt Thomas, Kilian Evang, Gergely Risko, Kristian Rumberg,
Peter Kropf, Mark Hepburn, greymont, D. Joe Anderson, Jeremy Zunker, ctebo,
Manuel Roumain, Jason Walsh, np, Shawn, Johan Tibell, Branden Tyree, Dinyar
Rabady, Andrew Mason, damond armstead, Ethan Aubin, TomTom Tommie, Jimmy
Kaplowitz, Steven Zakulec, mike smith, Jacob Kirkwood, Mark Hymers, Nathan
Collins, Asbjørn Sloth Tønnesen, Misty De Meo, James Shubin,
Jim Paris, Adam Sjøgren, miniBill, Taneli, Kumar Appaiah, Greg Grossmeier,
Sten Turpin, Otavio Salvador, Teemu Hukkanen, Brian Stengaard, bob walker,
bibeneus, andrelo, Yaroslav Halchenko, hesfalling, Tommy L, jlargentaye,
Serafeim Zanikolas, Don Armstrong, Chris Cormack, shayne.oneill, Radu
Raduta, Josh S, Robin Sheat, Henrik Mygind, kodx, Christian, Geoff
Crompton, Brian May, Olivier Berger, Filippo Gadotti, Daniel Curto-Millet,
Eskild Hustvedt, Douglas Soares de Andrade, Tom L, Michael Nacos, Michaël
P., William Roe, Joshua Honeycutt, Brian Kelly, Nathan Rasch, jorge, Martin
Galese, alex cox, Avery Brooks, David Whittington, Dan Martinez, Forrest
Sutton, Jouni K. Seppänen, Arnold Cano, Robert Beaty, Daniel, Kevin Savetz,
Randy, Ernie Braganza, Aaron Haviland, Brian Brunswick, asmw, sean, Michael
Williams, Alexander, Dougal Campbell, Robert Bacchas, Michael Lewis, Collin
Price, Wes Frazier, Matt Wall, Brandon Barclay, Derek van Vliet, Martin
DeMello, kitt hodsden, Stephen Kitt, Leif Bergman, Simon Lilburn, Michael
Prokop, Christiaan Conover, Nick Coombe, Tim Dysinger, Brandon Robinson,
Philip Newborough, keith, Mike Fullerton, Kyle, Phil Windley, Tyler Head,
George V. Reilly, Matthew, Ali Gündüz, Vasyl Diakonov, Paolo Capriotti,
allanfranta, Martin Haeberli, msingle, Vincent Sanders, Steven King, Dmitry
Gribanov, Brandon High, Ben Hughes, Mike Dank, JohnE, Diggory Hardy,
Michael Hanke, valhalla, Samuli Tuomola, Jeff Rau, Benjamin Lebsanft, John
Drago, James, Aidan Cooper, rondie, Paul Kohler, Matthew Knights, Aaron
Junod, Patrick R McDonald, Christopher Browne, Daniel Engel, John SJ
Anderson, Peter Sarossy, Mike Prasad, Christoph Ender, Jan Dittberner,
Zohar, Alexander Jelinek, stefan, Danny O'Brien, Matthew Thode, Nicole
Aptekar, maurice gaston, Chris Adams, Mike Klemencic, Reedy, Subito, Tobias
Gruetzmacher, Ole-Morten Duesund, André Koot, mp, gdop, Cole Scott, Blaker,
Matt Sottile, W. Craig Trader, Louis-Philippe Dubrule, Brian Boucheron,
Duncan Smith, Brenton Buchbach, Kyle Stevenson, Eliot Lash, Egon Elbre,
Praveen, williamji, Thomas Schreiber, Neil Ford, Ryan Pratt, Joshua Brand,
Peter Cox, Markus Engstrom, John Sutherland, Dean Bailey, Ed Summers,
Hillel Arnold, David Fiander, Kurt Yoder, Trevor Muñoz, keri, Ivan
Sergeyenko, Shad Bolling, Tal Kelrich, Steve Presley, gerald ocker, Essex
Taylor, Josh Thomson, Trevor Bramble, Lance Higgins, Frank Motta, Dirk
Kraft, soundray, Joe Haskins, nmjk, Apurva Desai, Colin Dean, docwhat,
Joseph Costello, Jst, flamsmark, Alex Lang, Bill Traynor, Anthony David,
Marc-André Lureau, AlNapp, Giovanni Moretti, John Lawrence, João Paulo
Pizani Flor, Jim Ray, Gregory Thrush, Alistair McGann, Andrew Wied,
Koutarou Furukawa, Xiscu Ignacio, Aaron Sachs, Matt, Quirijn, Chet
Williams, Chris Gray, Bruce Segal, Tom Conder, Louis Tovar, Alex Duryee,
booltox, d8uv, Decklin Foster, Rafael Cervantes, Micah R Ledbetter, Kevin
Sjöberg, Johan Strombom, Zachary Cohen, Jason Lewis, Yves Bilgeri, Ville
Aine, Mark Hurley, Marco Bonetti, Maximilian Haack, Hynek Schlawack,
Michael Leinartas, Andreas Liebschner, Duotrig, Nat Fairbanks, David
Deutsch, Colin Hayhurst, calca, Kyle Goodrick, Marc Bobillier, Robert
Snook, James Kim, Olivier Serres, Jon Redfern, Itai Tavor, Michael
Fladischer, Rob, Jan Schmid, Thomas H., Anders Söderbäck, Abhishek
Dasgupta, Jeff Goeke-Smith, Tommy Thorn, bonuswavepilot, Philipp Edelmann,
Nick, Alejandro Navarro Fulleda, Yann Lallemant, andrew brennan,
Dave Allen Barker Jr, Fabian, Lukas Anzinger, Carl Witty, Andy Taylor,
Andre Klärner, Andrew Chilton, Adam Gibbins, Alexander Wauck, Shane O'Dea,
Paul Waite, Iain McLaren, Maggie Ellen Robin Hess, Willard Korfhage,
Nicolas, Eric Nikolaisen, Magnus Enger, Philipp Kern, Andrew Alderwick,
Raphael Wimmer, Benjamin Schötz, Ana Guerrero, Pete, Pieter van der Eems,
Aaron Suggs, Fred Benenson, Cedric Howe, Lance Ivy, Tieg Zaharia, Kevin
Cooney, Jon Williams, Anton Kudris, Roman Komarov, Brad Hilton, Rick Dakan,
Adam Whitcomb, Paul Casagrande, Evgueni Baldin, Robert Sanders, Kagan
Kayal, Dean Gardiner, micah altman, Cameron Banga, Ross Mcnairn, Oscar
Vilaplana, Robin Graham, Dan Gervais, Jon Åslund, Ragan Webber, Noble Hays,
stephen brown, Sean True, Maciek Swiech, faser, eikenberry, Kai Laborenz,
Sergey Fedoseev, Chris Fournier, Svend Sorensen, Greg K, wojtek, Johan
Ribenfors, Anton, Benjamin, Oleg Tsarev, PsychoHazard, John Cochrane,
Kasper Lauritzen, Patrick Naish, Rob, Keith Nasman, zenmaster, David Royer,
Max Woolf, Dan Gabber, martin rhoads, Martin Schmidinger, Paul
Scott-Wilson, Tom Gromak, Andy Webster, Dale Webb, Jim Watson, Stephen
Hansen, Mircea, Dan Goodenberger, Matthias Fink, Andy Gott, Daniel, Jai
Nelson, Shrayas Rajagopal, Vladimir Rutsky, Alexander, Thorben Westerhuys,
hiruki, Tao Neuendorffer Flaherty, Elline, Marco Hegenberg, robert, Balda,
Brennen Bearnes, Richard Parkins, David Gwilliam, Mark Johnson, Jeff Eaton,
Reddawn90, Heather Pusey, Chris Heinz, Colin, Phatsaphong Thadabusapa,
valunthar, Michael Martinez, redlukas, Yury V. Zaytsev, Blake, Tobias
"betabrain" A., Leon, sopyer, Steve Burnett, bessarabov, sarble, krsch.com,
Jack Self, Jeff Welch, Sam Pettiford, Jimmy Stridh, Diego Barberá, David
Steele, Oscar Ciudad, John Braman, Jacob, Nick Jenkins, Ben Sullivan, Brian
Cleary, James Brosnahan, Darryn Ten, Alex Brem, Jonathan Hitchcock, Jan
Schmidle, Wolfrzx99, Steve Pomeroy, Matthew Sitton, Finkregh, Derek Reeve,
GDR!, Cory Chapman, Marc Olivier Chouinard, Andreas Ryland, Justin, Andreas
Persenius, Games That Teach, Walter Somerville, Bill Haecker, Brandon
Phenix, Justin Shultz, Colin Scroggins, Tim Goddard, Ben Margolin, Michael
Martinez, David Hobbs, Andre Le, Jason Roberts, Bob Lopez, Gert Van Gool,
Robert Carnel, Anders Lundqvist, Aniruddha Sathaye, Marco Gillies, Basti
von Bejga, Esko Arajärvi, Dominik Deobald, Pavel Yudaev, Fionn Behrens,
Davide Favargiotti, Perttu Luukko, Silvan Jegen, Marcelo Bittencourt,
Leonard Peris, smercer, Alexandre Dupas, Solomon Matthews, Peter Hogg,
Richard E. Varian, Ian Oswald, James W. Sarvey, Ed Grether, Frederic
Savard, Sebastian Nerz, Hans-Chr. Jehg, Matija Nalis, Josh DiMauro, Jason
Harris, Adam Byrtek, Tellef, Magnus, Bart Schuurmans, Giel van Schijndel,
Ryan, kiodos, Richard 'maddog' Collins, PawZubr, Jason Gassel, Alex
Boisvert, Richard Thompson, maddi bolton, csights, Aaron Bryson, Jason Chu,
Maxime Côté, Kineteka Systems, Joe Cabezas, Mike Czepiel, Rami Nasra,
Christian Simonsen, Wouter Beugelsdijk, Adam Gibson, Gal Buki, James
Marble, Alan Chambers, Bernd Wiehle, Simon Korzun, Daniel Glassey, Eero af
Heurlin, Mikael, Timo Engelhardt, Wesley Faulkner, Jay Wo, Mike Belle,
David Fowlkes Jr., Karl-Heinz Strass, Ed Mullins, Sam Flint,
Hendrica, Mark Emer Anderson, Joshua Cole, Jan Gondol, Henrik Lindhe,
Albert Delgado, Patrick, Alexa Avellar, Chris, sebsn1349, Maxim Kachur,
Andrew Marshall, Navjot Narula, Alwin Mathew, Christian Mangelsdorf, Avi
Shevin, Kevin S., Guillermo Sanchez Estrada, Alex Krieger, Luca Meier, Will
Jessop, Nick Ruest, Lani Aung, Ulf Benjaminsson, Rudi Engelbrecht, Miles
Matton, Cpt_Threepwood, Adam Kuyper, reacocard, David Kilsheimer, Peter
Olson, Bill Fischofer, Prashant Shah, Simon Bonnick, Alexander Grudtsov,
Antoine Boegli, Richard Warren, Sebastian Rust, AlmostHuman, Timmy
Crawford, PC, Marek Belski, pontus, Douglas S Butts, Eric Wallmander, Joe
Pelar, VIjay, Trahloc, Vernon Vantucci, Matthew baya, Viktor Štujber,
Stephen Akiki, Daniil Zamoldinov, Atley, Chris Thomson, Jacob Briggs, Falko
Richter, Andy Schmitz, Sergi Sagas, Peder Refsnes, Jonatan, Ben, Bill
Niblock, Agustin Acuna, Jeff Curl, Tim Humphrey, bib, James Zarbock,
Lachlan Devantier, Michal Berg, Jeff Lucas, Sid Irish, Franklyn, Jared
Dickson, Olli Jarva, Adam Gibson, Lukas Loesche, Jukka Määttä, Alexander
Lin, Dao Tran, Kirk, briankb, Ryan Villasenor, Daniel Wong, barista, Tomas
Jungwirth, Jesper Hansen, Nivin Singh, Alessandro Tieghi, Billy Roessler,
Peter Fetterer, Pallav Laskar, jcherney, Tyler Wang, Steve, Gigahost, Beat
Wolf, Hannibal Skorepa, aktiveradio, Mark Nunnikhoven, Bret Comnes, Alan
Ruttenberg, Anthony DiSanti, Adam Warkiewicz, Brian Bowman, Jonathan, Mark
Filley, Tobias Mohr, Christian St. Cyr, j. faceless user, Karl Miller,
Thomas Taimre, Vikram, Jason Mountcastle, Jason, Paul Elliott, Alexander,
Stephen Farmer, rayslava, Peter Leurs, Sky Kruse, JP Reeves, John J Schatz,
Martin Sandmair, Will Thompson, John Hergenroeder, Thomas, Christophe
Ponsart, Wolfdog, Eagertolearn, LukasM, Federico Hernandez, Vincent Bernat,
Christian Schmidt, Cameron Colby Thomson, Josh Duff, James Brown, Theron
Trowbridge, Falke, Don Meares, tauu, Greg Cornford, Max Fenton, Kenneth
Reitz, Bruce Bensetler, Mark Booth, Herb Mann, Sindre Sorhus, Chris
Knadler, Daniel Digerås, Derek, Sin Valentine, Ben Gamari, david
lampenscherf, fardles, Richard Burdeniuk, Tobias Kienzler, Dawid Humbla,
Bruno Barbaroxa, D Malt, krivar, James Valleroy, Peter, Tim Geddings,
Matthias Holzinger, Hanen, Petr Vacek, Raymond, Griff Maloney, Andreas
Helveg Rudolph, Nelson Blaha, Colonel Fubar, Skyjacker Captain Gavin
Phoenix, shaun, Michael, Kari Salminen, Rodrigo Miranda, Alan Chan, Justin
Eugene Evans, Isaac, Ben Staffin, Matthew Loar, Magos, Roderik, Eugenio
Piasini, Nico B, Scott Walter, Lior Amsalem, Thongrop Rodsavas, Alberto de
Paola, Shawn Poulen, John Swiderski, lluks, Waelen, Mark Slosarek, Jim
Cristol, mikesol, Bilal Quadri, LuP, Allan Nicolson, Kevin Washington,
Isaac Wedin, Paul Anguiano, ldacruz, Jason Manheim, Sawyer, Jason
Woofenden, Joe Danziger, Declan Morahan, KaptainUfolog, Vladron, bart, Jeff
McNeill, Christian Schlotter, Ben McQuillan, Anthony, Julian, Martin O,
altruism, Eric Solheim, MarkS, ndrwc, Matthew, David Lehn, Matthew
Cisneros, Mike Skoglund, Kristy Carey, fmotta, Tom Lowenthal, Branden
Tyree, Aaron Whitehouse

### Also thanks to

* The Kickstarter team, who have unleashed much good on the world.
* The Haskell developers, who toiled for 20 years in obscurity
  before most of us noticed them, and on whose giant shoulders I now stand,
  in awe of the view.
* The Git developers, for obvious reasons.
* All of git-annex's early adopters, who turned it from a personal
  toy project into something much more, and showed me the interest was there.
* Rsync.net, for providing me a free account so I can make sure git-annex
  works well with it.
* LeastAuthority.com, for providing me a free Tahoe-LAFS grid account,
  so I can test git-annex with that, and back up the git-annex assistant
  screencasts.
* Anna and Mark, for the loan of the video camera; as well as the rest of
  my family, for your support. Even when I couldn't explain what I was
  working on.
* The Hodges, for providing such a congenial place for me to live and work
  on these first world problems, while you're off helping people in the
  third world.


code:
This page is a place to document tips and techniques for using git-annex.

[[!inline pages="tips/* and !tips/*/*" archive="yes"
rootpage="tips" postformtext="Add a new tip about:" show=0]]

repo_name: kakafarm/git

license: unknown


code:
I've been wrestling with git-annex to try to make it build on Debian, or more specifically, wrestling with Haskell dependencies.

After a fair amount of futzing around, and pestering a bunch of people in the process (thanks for the help! :) ) I finally managed to make it build.

I figured I would post the steps here, since it's not completely trivial, and I expect that a few others might be interested in building newer versions as well.

There appears to currently be two methods:

* Debian packages on Wheezy plus Sid
  * Starting out on Wheezy, and then picking the rest from Sid (it seems at least libghc-safesemaphore-dev from Sid is critical for newer git-annex)
  * WebDAV suport will not be available with this method
* Cabal packages

#Debian packages on Wheezy plus Sid

##Start off with a clean wheezy chroot

    sudo debootstrap wheezy debian-wheezy
    sudo chroot debian-wheezy

##Install some build tools

    apt-get update
    apt-get install devscripts git

##Get git-annex (either by cloning or simply moving the source into the chroot)

    mkdir /src
    cd /src
    git clone git://git-annex.branchable.com/source.git git-annex
    cd git-annex

##Remove WebDAV dependency which can't be satisfied anywhere

    sed '/libghc-dav-dev/d' -i debian/control

##Create dummy build-depends package and install all available Wheezy dependencies using it

    mk-build-deps
    dpkg -i git-annex-build-deps*.deb
    apt-get install -f

(this will remove the build-depends package)

##Add Sid sources and install all available Sid dependencies

    echo "deb http://http.debian.net/debian sid main" >>/etc/apt/sources.list
    apt-get update
    dpkg -i git-annex-build-deps*.deb
    apt-get install -f

(the build-depends package should now be fully installed)

##Disable the 'make test' that fails due to missing hothasktags

    echo >>debian/rules
    echo "override_dh_auto_test:" >>debian/rules

##Build!

    debuild -us -uc -Igit

#Cabal packages

##Start off with a clean Sid(/Wheezy) chroot

    sudo debootstrap sid debian-sid
    sudo chroot debian-sid

##Install a smaller set of tools and build-depends from Debian (cabal needs these to compile the Haskell stuff)

    apt-get update
    apt-get install ghc cabal-install devscripts libz-dev pkg-config c2hs libgsasl7-dev libxml2-dev libgnutls-dev c2hs git debhelper ikiwiki perlmagick uuid rsync openssh-client fakeroot

##Get git-annex (either by cloning or simply moving the source into the chroot)

    mkdir /src
    cd /src
    git clone git://git-annex.branchable.com/source.git git-annex
    cd git-annex

##Install the Haskell build-dependencies from cabal

    cabal update
    cabal install --only-dependencies

##Optional step which doesn't work (might in the future)
If we want to run the 'make test' after build we need hothasktags, which is only available via cabal

    apt-get install happy
    cabal install hothasktags
    export PATH=$PATH:~/.cabal/bin

But this currently fails silently inside make test->fast->tags, and if you dig a bit (manually edit the makefile to be more verbose) you see

    hothasktags: ./Command/AddUnused.hs: hGetContents: invalid argument (invalid byte sequence)

##Disable the 'make test' that fails

    echo >>debian/rules
    echo "override_dh_auto_test:" >>debian/rules

##Remove all Debian package haskell depends (taken care of by cabal instead)

    sed '/\tlibghc/d' -i debian/control

## Build!

    debuild -us -uc -Igit


code:
[[!comment format=mdwn
 username="https://www.google.com/accounts/o8/id?id=AItOawkCw26IdxXXPBoLcZsQFslM67OJSJynb1w"
 nickname="Alexander"
 subject="can't install git-annex on OS X Mountain Lion without disabling WebDAV support"
 date="2013-04-29T17:57:03Z"
 content="""
possibly related to this Debian issue:

trying to install git-annex with cabal on OS X 10.8.3, the build fails with

    Loading package DAV-0.4 ... linking ... ghc:
    lookupSymbol failed in relocateSection (relocate external)
    ~/.cabal/lib/DAV-0.4/ghc-7.4.2/HSDAV-0.4.o: unknown symbol `_DAVzm0zi4_PathszuDAV_version1_closure'
    ghc: unable to load package `DAV-0.4'
    Failed to install git-annex-4.20130417
    cabal: Error: some packages failed to install:
    git-annex-4.20130417 failed during the building phase. The exception was:
    ExitFailure 1

This was after following all of the instructions for the Homebrew install at [http://git-annex.branchable.com/install/OSX/](http://git-annex.branchable.com/install/OSX/)
I was able to work around this issue by installing with the WebDAV flag disabled (ie, added the option --flags=\"-WebDAV\" to last command in the OS X install instructions):

    cabal install git-annex --bindir=$HOME/bin --flags=\"-WebDAV\"

"""]]


code:
[[!comment format=mdwn
 username="http://joeyh.name/"
 nickname="joey"
 subject="comment 2"
 date="2013-04-30T21:51:50Z"
 content="""
@Alexander that DAV-0.4 problem is a bug in DAV, not git-annex. I've informed its author and it should be fixed soon, in a new version of DAV.
"""]]


code:
Here's a workaround to start syncing folders on Windows right now. It's a bit command line heavy, so you might need to set this up for your users. But I would much rather do this than use some other syncing solution and then have to migrate.

(1) Create a remote server git annex repository with the assistant on Linux or Mac.

(2) [Install git](http://git-scm.com/) on the Windows machine.

(3) [Install git-annex for Windows](http://git-annex.branchable.com/install/Windows/) on the Windows machine. Don't forget to run the installer as administrator.

(4) Run _Git Bash_ from the system menu, and run these commands to clone your repository.

    ssh-keygen
    cat .ssh/id_rsa.pub | ssh username@my-server.com "cat >> ~/.ssh/authorized_keys"
    git clone username@my-server.com:/path/to/annex
    cd annex
    git annex init

(5) Create a script that will trigger a full sync

    echo '
    #!/bin/bash
    git annex sync
    git annex get *
    git annex add .
    git annex sync
    git annex copy * --to origin
    ' > sync.sh
    chmod +x sync.sh
    ./sync.sh

(6) Copy the "Git Bash" shortcut from your windows menu to your desktop, and change the link target to:

    C:\Program Files\Git\bin\sh.exe" --login -i "annex/sync.sh"

Now ask your users to run this shortcut before and after they change files. You can also put it into the "autostart" folder to sync at boot.


code:
If you're anything like me¹, you have a copy of your annex on a computer running at home², set up so you can access it from anywhere like this:

    ssh myhome.no-ip.org

This is totally great! Except, there is no way for your home computer to pull your changes, because there is no *on-the-go.no-ip.org*. You can get clunky and use a *bare git repository and git push*, but there is a better way.

First, install *openssh-server* on your *on-the-go* computer

    sudo apt-get install openssh-server # Adjust to your flavor of unix

Then, log into your *home* computer, with *port forwarding*:

    ssh me@myhome.no-ip.org -R 2201:localhost:22

Your *home* computer can now ssh into your *on-the-go* computer, as long as you keep the above shell running.

You can now add your *on-the-go* computer as a remote on your *home* computer. Use the port forwarding shell you just connected with the command above, if you like.

    ssh-keygen -t rsa
    ssh-copy-id "me@localhost -p 2201"
    cd ~/annex
    git remote add on-the-go ssh://me@localhost:2201/home/myuser/annex

Now you can run normal annex operations, as long as the port forwarding shell is running³.

    git annex sync
    git annex get on-the-go some/big/file
    git annex info

You can add more computers by repeating with a different port, e.g. 2202 or 2203 (or any other).

If you're security paranoid (like me), read on. If you're not, that's it! Thanks for reading!

---
Paranoid Area

Note you're granting passwordless access to your on-the-go computer to your home computer. I believe that's all right, as long as:

* Your home computer is really in your home, and not at a friend's house or some datacenter
* Your home computer can be accessed only by ssh, and not HTTP or Samba or NTP or (shoot me now!) FTP
* Only you (and perhaps trustworthy family) have access to your home computer
* You have reasonably strong passwords or key-only logins on both your home and on-the-go computers.
* You regularly install security updates on both computers (sudo apt-get update && sudo apt-get upgrade)

In any case, the setup is much, much, much more secure than Dropbox. With Dropbox, you have exactly the same setup, but:

* Your data is stored in some datacenter. It's supposed to be encrypted. It might not be.
* Lot's of people have routine access to your files, and plausible reason to. Bored employees might regularly be doing some 'maintenance work' involving your pictures.
* The dropbox software can do anything it likes on your computer, and it's closed source so you don't know if it does. A disgruntled employee could put a trojan into it.
* Dropbox might have a backdoor for employee access to any file on your computer. This might be done with the best of intentions, but a mal-intentioned or careless employee might still erase things or send sensitive files from your computer by email.
* A truly huge amount of eyes connected to incredibly smart brains have looked at openssh and found it secure. Everybody trusts openssh. With dropbox, there is, well, dropbox. Whoever that is.

-----

¹ Me=Carlo, not Joey. I'm pretty sure doing what I wrote here is a good idea, but in case it turns out to be catastrophically dumb, it's my fault, not his.

² My always-on computer at home is a raspberry pi with a 32GB USB stick. Best self-hosted dropbox you could imagine.

³ You can just forward the port, but not open a shell, by adding the -N command. This could be useful for connecting on startup, e.g. in /etc/rc.local. I prefer to open the shell to forward the ports, maybe use it, and close it to stop it.


code:
[[!comment format=mdwn
 username="http://joeyh.name/"
 ip="4.154.6.49"
 subject="comment 1"
 date="2012-11-30T16:25:58Z"
 content="""
If you don't trust your home computer with shell access, you can lock it down in `.ssh/authorized_keys` to only be able to run git-annex-shell. See [[forum/Restricting_git-annex-shell_to_a_specific_repository]]
"""]]


code:
# Problem
I noticed that after installing git-annex assistant, my start up times greatly increased because the assistant does a startup scan while everything else is loading.
# Solution (for people using Gnome)
The solution I came up with is to delay the assistant's startup, as well as setting its IO priority as idle. To do this in Gnome 3, run:

    gnome-session-properties
Find the "Git Annex Assistant" entry in the Startup Programs tab, then click edit. Change this:

    /usr/local/bin/git-annex assistant --autostart (your location of git-annex may be different)
to this:

    bash -c "sleep 30; ionice -c3 /usr/local/bin/git-annex assistant --autostart" (replace /usr/local/bin to wherever git-annex is installed)
The "sleep 30" command delays the startup of the assistant by 30 seconds, and "ionice -c3" sets git-annex's IO priority to "idle," the lowest level.


code:
[[!comment format=mdwn
 username="https://launchpad.net/~alphapapa"
 nickname="alphapapa"
 subject="ionice not supported by deadline scheduler"
 date="2013-06-28T17:43:47Z"
 content="""
Linux's deadline I/O scheduler does not support ionice.  It is now the default on some distros, including Ubuntu.  CFQ does support ionice.
"""]]


code:
The problem
===========

[Calibre](http://calibre-ebook.com/) is a ebook manager that is
available in [debian](http://packages.debian.org/sid/calibre). I use
it to maintain my library, but also to dowload every day an epub
version of a French newspaper and then put it on my kobo.

Configuring git annex for this
==============================

I wanted to use git-annex, so

    $ git init
    $ git annex init "some useful name"

But I don't want every thing in annex, because Calibre use some text
file to save some metadata, so I used:

    $ git config annex.largefiles "include=* exclude=*.opf exclude=*.json"

then lets add everything

    $ git annex add *
    $ git add *
    $ git commit -m "first commit"

Calibre need read and write access on the its database, so let unlock it:

    $ git annex unlock metadata.db

On my other computer I only need to do

    $ git clone $user@$host:Calibre\ library
    $ cd Calibre\ library
    $ git annex init "another useful name"
    $ git annex get .
    $ git annex unlock metadata.db

The problem is that every time you will `git annex sync`, git annex
will lock again the metadata.db, so lets unlock it automatically. I
use git hooks, in `.git/hooks/post-commit` I have

    #!/bin/bash

    git annex edit metadata.db

don't forget to make this file executable

    $ chmod a+x .git/hooks/post-commit

Day to day operation
====================

    $ git annex add .

Will put new file into the annex

    $ git add .

Will take care of the files that should no go into annex

    $ git annex sync

Will make the repositories exchange informations about all this, and
make remote change local

    $ git annex get .

Will make remote book locally available

Merge conflict
--------------
You should not run calibre on the two computer simultaneously, or
without syncing before it. If you do, you will have a conflict that
git-annex will automatically *solve* by rename both of the file.

You can then either:

 - Choose one. If no books have been changed or added on one of the
   computer, to use the other `metadata.db` will not make you loose
   any information
 - rebuild it. `calibredb restore_database` won't do it, but will tell
   you how to do it.

Checking the library
--------------------
You can use `calibredb check_library` to check you library is
correct. If you use git for it, it will always tell you that it is not
correct: there is this author ".git" it doesn't know about. Just don't
care about it.

Maybe this can be solved by using `vcsh` but apparently
`vcsh`+`git annex` it not well tested yet.

Automatic stuff
---------------
I use `mr` to automatically run all this, but some config could be
done (I believe) to have `git annex copy --auto` do what it should.

There are also the git annex assistant for this kind of automatic
synchronizations of contents, but I don't know if my automatic
unlocking of one file will break this.

It might be interesting to find someway to unlock and lock the library
only when running calibre, a simple script to launch calibre will do
that. Note that each time you will lock and unlock, you will have a
new commit in git.

Another solution
===================
You could also use direct mode in place of the auto unlock feature

    git annex direct

The remove the `post-commit` git hook (or do not add it). Its a
simpler solution, but remember that interaction between git annex direct
repositories and plain git are complex and sometimes downright dangerous. See [[direct mode]] for details.

In particular, do *not* called `git add *` in the above steps, as that will commit all books into git.


code:
I worked out how to retroactively annex a large file that had been checked into a git repo some time ago.  I thought this might be useful for others, so I am posting it here.

Suppose you have a git repo where somebody had checked in a large file you would like to have annexed, but there are a bunch of commits after it and you don't want to loose history, but you also don't want everybody to have to retrieve the large file when they clone the repo.  This will re-write history as if the file had been annexed when it was originally added.

This command works for me, it relies on the current behavior of git which is to use a directory named .git-rewrite/t/ at the top of the git tree for the extracted tree.  This will not be fast and it will rewrite history, so be sure that everybody who has a copy of your repo is OK with accepting the new history.  If the behavior of git changes, you can specify the directory to use with the -d option.  Currently, the t/ directory is created inside the directory you specify, so "-d ./.git-rewrite/" should be roughly equivalent to the default.

Enough with the explanation, on to the command:

git filter-branch --tree-filter 'for FILE in file1 file2 file3;do if [ -f "$FILE" ] && [ ! -L "$FILE" ];then git rm --cached "$FILE";git annex add "$FILE";ln -sf `readlink "$FILE"|sed -e "s:^../../::"` "$FILE";fi;done' --tag-name-filter cat -- --all

replace file1 file2 file3... with whatever paths you want retroactively annexed.  If you wanted bigfile1.bin in the top dir and subdir1/bigfile2.bin to be retroactively annexed try:

git filter-branch --tree-filter 'for FILE in bigfile1.bin subdir1/bigfile2.bin;do if [ -f "$FILE" ] && [ ! -L "$FILE" ];then git rm --cached "$FILE";git annex add "$FILE";ln -sf `readlink "$FILE"|sed -e "s:^../../::"` "$FILE";fi;done' --tag-name-filter cat -- --all

**If your repo has tags** then you should take a look at the git-filter-branch man page about the --tag-name-filter option and decide what you want to do.  By default this will re-write the tags "nearly properly".

You'll probably also want to look at the git-filter-branch man page's section titled "CHECKLIST FOR SHRINKING A REPOSITORY" if you want to free up the space in the existing repo that you just changed history on.


code:
[[!comment format=mdwn
 username="http://edheil.wordpress.com/"
 ip="173.162.44.162"
 subject="comment 1"
 date="2012-12-16T00:11:38Z"
 content="""
Man, I wish you'd written this a couple weeks ago. :)  I was never able to figure that incantation out and ended up unannexing and re-annexing the whole thing to get rid of the file I inadvertently checked into git instead of the annex.
"""]]


code:
[[!comment format=mdwn
 username="https://launchpad.net/~arand"
 nickname="arand"
 subject="comment 2"
 date="2013-03-13T12:05:49Z"
 content="""
Based on the hints given here I've worked on a filter to both annex and add urls via filter-branch:

[https://gitorious.org/arand-scripts/arand-scripts/blobs/master/annex-filter](https://gitorious.org/arand-scripts/arand-scripts/blobs/master/annex-filter)

The script above is very specific but I think there are a few ideas that can be used in general, the general structure is

    #!/bin/bash

    # links that already exist
    links=$(mktemp)
    find . -type l >\"$links\"

    # remove from staging area first to not block and then annex
    git rm --cached --ignore-unmatch -r bin*
    git annex add -c annex.alwayscommit=false bin*

    # compare links before and after annexing, remove links that existed before
    newlinks=$(mktemp -u)
    mkfifo \"$newlinks\"
    comm -13 <(sort \"$links\") <(find . -type l | sort) > \"$newlinks\" &

    # rewrite links
    while IFS= read -r file
    do
        # link is created below .git-rewrite/t/ during filter-branch, strip two parents for correct target
        ln -sf \"$(readlink \"$file\" | sed -e 's%^\.\./\.\./%%')\" \"$file\"
    done < \"$newlinks\"

    git annex merge

which would be run using

    git filter-branch --tree-filter path/annex-filter --tag-filter cat -- --all

or similar.

* I'm using `find` to make sure the only rewritten symlinks are for the newly annexed files, this way it is possible to annex an unknown set of filenames
* If doing several git annex commands using `-c annex.alwayscommit=false` and doing a `git annex merge` at the end instead might be faster.
"""]]


code:
[[!comment format=mdwn
 username="arand"
 ip="130.238.245.202"
 subject="comment 3"
 date="2013-03-18T14:39:52Z"
 content="""
One thing I noticed is that git-annex needs to checksum each file even if they were previously annexed (rather obviously since there is no general way to tell if the file is the same as the old one without checksumming), but in the specific case that we are replacing files that are already in git, we do actually have the sha1 checksum for each file in question, which could be used.

So, trying to work with this, I wrote a filter script that starts out annexing stuff in the first commit, and continously writes out sha1<->filename<->git-annex-object triplets to a global file, when it then starts with the next commit, it compares the sha1s of the index with those of the global file, and any matches are manually symlinked directly to the corresponding git-annex-object without checksumming.

I've done a few tests and this seems to be considerably faster than letting git-annex checksum everything.

This is from a git-svn import of the (free software) Red Eclipse game project, there are approximately 3500 files (images, maps, models, etc.) being annexed in each commit (and around 5300 commits, hence why I really, really care about speed):

10 commits: ~7min

100 commits: ~38min

For comparison, the old and new method (the difference should increase with the amount of commits):

old, 20 commits ~32min

new, 20 commits: ~11min

The script itself is a bit of a monstrosity in bash(/grep/sed/awk/git), and the files that are annexed are hardcoded (removed in forming $oldindexfiles), but should be fairly easy to adapt:

[https://gitorious.org/arand-scripts/arand-scripts/blobs/master/annex-ffilter](https://gitorious.org/arand-scripts/arand-scripts/blobs/master/annex-ffilter)

The usage would be something like:

    rm /tmp/annex-ffilter.log; git filter-branch --tree-filter 'ANNEX_FFILTER_LOG=/tmp/annex-ffilter.log ~/utv/scripts/annex-ffilter' --tag-name-filter cat -- branchname

I suggest you use it with at least two orders of magnitude more caution than normal filter-branch.

Hope it might be useful for someone else wrestling with filter-branch and git-annex :)
"""]]


code:
[[!comment format=mdwn
 username="https://www.google.com/accounts/o8/id?id=AItOawknOATcOkmzX4jKuET5Z2RsaFUNnLKnQsU"
 nickname="Stephen"
 subject="comment 4"
 date="2013-06-22T07:43:09Z"
 content="""
Thanks for the tip :) One question though: how do I push this new history out throughout my other Annexes?
All I managed to make it do was revert the rewrite so the raw file appeared again...
"""]]


code:
[The Internet Archive](http://www.archive.org/) allows members to upload
collections using an Amazon S3
[compatible API](http://www.archive.org/help/abouts3.txt), and this can
be used with git-annex's [[special_remotes/S3]] support.

So, you can locally archive things with git-annex, define remotes that
correspond to "items" at the Internet Archive, and use git-annex to upload
your files to there. Of course, your use of the Internet Archive must
comply with their [terms of service](http://www.archive.org/about/terms.php).

A nice added feature is that whenever git-annex sends a file to the
Internet Archive, it records its url, the same as if you'd run `git annex
addurl`. So any users who can clone your repository can download the files
from archive.org, without needing any login or password info. This makes
the Internet Archive a nice way to publish the large files associated with
a public git repository.

## webapp setup

Just go to "Add Another Repository", pick "Internet Archive",
and you're on your way.

## basic setup

Sign up for an account, and get your access keys here:
<http://www.archive.org/account/s3.php>

	# export AWS_ACCESS_KEY_ID=blahblah
	# export AWS_SECRET_ACCESS_KEY=xxxxxxx

Specify `host=s3.us.archive.org` when doing `initremote` to set up
a remote at the Archive. This will enable a special Internet Archive mode:
Encryption is not allowed; you are required to specify a bucket name
rather than having git-annex pick a random one; and you can optionally
specify `x-archive-meta*` headers to add metadata as explained in their
[documentation](http://www.archive.org/help/abouts3.txt).

	# git annex initremote archive-panama type=S3 \
		host=s3.us.archive.org bucket=panama-canal-lock-blueprints \
		x-archive-meta-mediatype=texts x-archive-meta-language=eng \
		x-archive-meta-title="original Panama Canal lock design blueprints"
	initremote archive-panama (Internet Archive mode) ok
	# git annex describe archive-panama "a man, a plan, a canal: panama"
	describe archive-panama ok

Then you can annex files and copy them to the remote as usual:

	# git annex add photo1.jpeg --backend=SHA256E
	add photo1.jpeg (checksum...) ok
	# git annex copy photo1.jpeg --fast --to archive-panama
	copy (to archive-panama...) ok

Once a file has been stored on archive.org, it cannot be (easily) removed
from it. Also, git-annex whereis will tell you a public url for the file
on archive.org. (It may take a while for archive.org to make the file
publically visibile.)

Note the use of the SHA256E [[backend|backends]] when adding files. That is
the default backend used by git-annex, but even if you don't normally use
it, it makes most sense to use the WORM or SHA256E backend for files that
will be stored in the Internet Archive, since the key name will be exposed
as the filename there, and since the Archive does special processing of
files based on their extension.

## publishing only one subdirectory

Perhaps you have a repository with lots of files in it, and only want
to publish some of them to a particular Internet Archive item. Of course
you can specify which files to send manually, but it's useful to
configure [[preferred_content]] settings so git-annex knows what content
you want to store in the Internet Archive.

One way to do this is using the "public" repository type.

	git annex enableremote archive-panama preferreddir=panama
	git annex wanted archive-panama standard
	git annex group archive-panama public

Now anything in a "panama" directory will be sent to that remote,
and anything else won't. You can use `git annex copy --auto` or the
assistant and it'll do the right thing.

When setting up an Internet Archive item using the webapp, this
configuration is automatically done, using an item name that the user
enters as the name of the subdirectory.


code:
[[!comment format=mdwn
 username="https://id.koumbit.net/anarcat"
 ip="72.0.72.144"
 subject="how to use with simply addurl?"
 date="2013-10-09T22:27:27Z"
 content="""
It doesn't seem like git annex addurl by itself supports the archive.org urls...

[[!format txt \"\"\"
anarcat@marcos:presentations$ git annex addurl --file=re_publica_2012___Eben_Moglen___Freedom_of_Thought_Requires_Free_Media.webm http://archive.org/download/Republica2012-EbenMoglen-FreedomOfThoughtRequiresFreeMedia/re_publica_2012___Eben_Moglen___Freedom_of_Thought_Requires_Free_Media.webm
addurl re_publica_2012___Eben_Moglen___Freedom_of_Thought_Requires_Free_Media.webm
  failed to verify url exists: http://archive.org/download/Republica2012-EbenMoglen-FreedomOfThoughtRequiresFreeMedia/re_publica_2012___Eben_Moglen___Freedom_of_Thought_Requires_Free_Media.webm
failed
git-annex: addurl: 1 failed
\"\"\"]]

I also tried the \"details\" url (<http://archive.org/details/Republica2012-EbenMoglen-FreedomOfThoughtRequiresFreeMedia>) - but that just downloads the webpage, not the video either...

Even the ultimate video URL doesn't work:

[[!format txt \"\"\"
anarcat@marcos:presentations$ git annex addurl --debug --file=re_publica_2012___Eben_Moglen___Freedom_of_Thought_Requires_Free_Media.webm http://ia601009.us.archive.org/9/items/Republica2012-EbenMoglen-FreedomOfThoughtRequiresFreeMedia/re_publica_2012___Eben_Moglen___Freedom_of_Thought_Requires_Free_Media.webm
[2013-10-09 18:26:30 EDT] call: quvi [\"-v\",\"mute\",\"--support\",\"http://ia601009.us.archive.org/9/items/Republica2012-EbenMoglen-FreedomOfThoughtRequiresFreeMedia/re_publica_2012___Eben_Moglen___Freedom_of_Thought_Requires_Free_Media.webm\"]
addurl re_publica_2012___Eben_Moglen___Freedom_of_Thought_Requires_Free_Media.webm [2013-10-09 18:26:30 EDT] read: curl [\"-s\",\"--head\",\"-L\",\"http://ia601009.us.archive.org/9/items/Republica2012-EbenMoglen-FreedomOfThoughtRequiresFreeMedia/re_publica_2012___Eben_Moglen___Freedom_of_Thought_Requires_Free_Media.webm\",\"-w\",\"%{http_code}\"]

  failed to verify url exists: http://ia601009.us.archive.org/9/items/Republica2012-EbenMoglen-FreedomOfThoughtRequiresFreeMedia/re_publica_2012___Eben_Moglen___Freedom_of_Thought_Requires_Free_Media.webm
failed
git-annex: addurl: 1 failed
\"\"\"]]

... even though that URL actually gives out a proper 200 OK response code.

Any ideas? --[[anarcat]]
"""]]


code:
[[!comment format=mdwn
 username="http://joeyh.name/"
 ip="4.154.4.22"
 subject="comment 2"
 date="2013-10-11T17:08:27Z"
 content="""
This was a misleading error message. The url you are trying to add to the file does not match the size recorded for the file already in the annex. (Or possibly the file's key has no recorded size). If you really want to add the url to the file despite it being a different encoding, you can use --relaxed, although fsck may not like the result if you ever end up downloading that url..

(Please file bug reports for problems in the future, rather than posting comments on only vaguely related pages which as we can see here can turn out to be entirely offtopic.)
"""]]


code:
[[!comment format=mdwn
 username="https://id.koumbit.net/anarcat"
 ip="72.0.72.144"
 subject="still a bug, filed separately!"
 date="2013-10-11T18:49:06Z"
 content="""
Aaah, of course, sorry for the noise here. It turns out that this is *not* because the filesize (or even the checksum, for that matter) are different, so there's clearly a bug there, and i filed it in [[bugs/addurl_fails_on_the_internet_archive]]. Thanks!
"""]]


code:
Combining git-annex with [Shamir secret sharing](http://en.wikipedia.org/wiki/Shamir%27s_Secret_Sharing)
is an useful way to securely back up highly sensitive files,
such as a gpg key or bitcoin wallet.

Shamir secret sharing creates N shares of a file, of which any M can be
used to reconstitute the original file. Anyone who has less than M shares
cannot tell anything about the original file, other than its size.

Where git-annex comes in is as a way to manage these shares. They can be
added to the annex, and then git-annex used to move one share to each clone
of the repository. Since git-annex keeps track of where each file is
stored, this can aid later finding the shares again when they're needed, as
well as making ongoing management of the shares easier.

Note that this conveniece comes at a price: Any attacker who gets a copy
of the git repository can use it to figure out where the shares are
located. While this is not a crippling flaw, and can be worked around, it
needs to be considered when implementing this technique.

Here is an example of this method being used for a ~/.gnupg directory:
<http://git.kitenet.net/?p=gpg.git;a=blob;f=README.sss>


code:
# How to use git-annex on a Synology NAS

This is known to work with DSM 4.3-3810 Update 1 and git-annex standalone version 5.20131224-g6ca5271.

## Installation Steps

(1) In the DSM Package Center, install Git, which is available from Synology (no third-party repository needed).

(2) Download the latest [[standalone|install/Linux_standalone]] git-annex build for Linux on armel.

(3) Extract it somewhere sensible (eg: a bin/ directory your users home directory)

(4) Go into the git-annex.linux directory and ./runshell. You can now run git-annex as you normally would.

## How to sync with the Synology NAS

### On the Synology
(1) Setup port forwarding and associated dynamic dns, if applicable. Many good guides online for this.

(2) Setup ssh key based authentication with the Synology for each computer you want to sync with it. You want a specific key that is used only by git-annex, for each computer. Again, many good guides online.

(3) In the Synology .ssh/authorized_keys file for your account, add (substituing your username)
[[!format sh """
command="/home/$yourusername/.ssh/git-annex-shell"
"""]]
to the beginning of the line. Eg, it would look like this:
[[!format sh """
command="/home/greg/.ssh/git-annex-shell" ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDT1yE96E/JQNPt0ziiNYJRvndCvLK4uG5h/SNYoAIBF1uH6L7VYAt3HWVqSyi3BcV70WDZ/yWgtNzbrcir46JpvEHMcvYaXLbANwoDGNjG/gsz7kP/8VUxZ6hG3P3ICuwnqVum5+rYXm6oj3xzWPfTRhhRoDZLOQdevSNpdGNaa/lSg8Vuq2suHwjQlQb8AIUuCZmS5cm6XwoUq/jJtN4LTuTPqMjzA6NkdhWM2Kigi9jPQBFborkYBPMphmZwBZiVnhsH1XpaOff+mP03D2gF/huC+b1vbWQstjuehUbY59rvJ4ijb3810Uq2ep7dwLagmILtX5GbL+GS64pAn9sIP annex-othercomputer
"""]]

(4) the git-annex-shell script in your .ssh should be created for you aftering your initial ./runshell

(5) Double check that the script points to the correct directory of where your extracted git-annex.linux lives.

### On the other computers - the manual way
(1) See step 2 above about creating the specific git-annex ssh keys.

(2) In your .ssh/config, create an alias for your Synology that includes specifying the right sshkey. For example, mine looks like:
[[!format sh """
Host synologyhost
    HostName mydynamicdomain.no-ip.org
    IdentityFile /home/greg/.ssh/annex_rsa
"""]]

(3) Now when you clone the git repo from the Synology, or add it as a remote, do the following:
[[!format sh """
git clone greg@synologyhost:/absolute/path/to/annexname annexname
"""]]
or

[[!format sh """
git remote add synology greg@synologyhost:/absolute/path/to/annexname
"""]]

(4) Run git-annex sync

### On the other computers - Using the assistant

(1) Use the webapp to add the remote. I'm not sure if there are any gotchas here as I have not done it this way yet.


code:
[[!comment format=mdwn
 username="https://www.google.com/accounts/o8/id?id=AItOawnrP-0DGtHDJbWSXeiyk0swNkK1aejoN3c"
 nickname="sebastien"
 subject="new dev site for syno dsm 5.0"
 date="2014-03-25T10:20:46Z"
 content="""
There is a new website with documentation to create App for new synology dsm 5.0 here : http://www.synology.com/en-us/support/developer
A good way to distribute git annex to lot of people ? :)
"""]]


code:
I have an annex that syncs my personal files on all my computers. It works great. Phones are different.

For one, everything's a bit slower to sync, there's battery considerations, and I just don't need every last old file on my phone. Then there's some files I explicitly don't want on my phone in case it gets lost, like family pictures, passport scans, or private keys.

But I still want photos, videos and voice recordings I make on my phone to be synced to my server. A transfer repo would work, but I want to keep them. Then there's my PDF book collection; that would certainly be nice to always have around in case I have half on hour on a bus. And my music collection ought to be around as well.

So I came up with this solution, and I'm very happy with it.

    include=Music/* or include=Books/* or present

This will sync my music and book collections to my phone whenever I add something new on my computers, and it will sync and keep anything I add to the annex on my phone. Best of all worlds! Impressed how flexible preferred content is. More full-sync folders can be added like this:

    include=Music/* or include=Books/* or include = Notes/* or present

To add them, I first had to figure out the uuid of my phone repo. So I added a new tab on android, and did

    cd /sdcard/annex
    git config annex.uuid

Then I went to one of my computers, and did

    git annex vicfg

And changed the line

    content [phone-uuid] = standard

to

    content [phone-uuid] = include=Music/* or include=Books/* or Notes/* or present

and commented out

    #group [phone-uuid] = client

And waited for it to sync.


code:
[[!comment format=mdwn
 username="http://joeyh.name/"
 ip="209.250.56.246"
 subject="comment 1"
 date="2013-11-16T17:29:03Z"
 content="""
That's great, that's how I hoped people would be able to use preferred content settings.

I'd suggest adding support for archive directories to this. So if you create a file on the phone and are done with it, you can move it to an archive directory, and it will then be dropped from the phone once it reaches an archive repository.

This should accomplish that. (Untested)

`((exclude=*/archive/* and exclude=archive/*) or (not (copies=archive:1 or copies=smallarchive:1))) and (include=Music/* or include=Books/* or present)`
"""]]


code:
[[!comment format=mdwn
 username="https://www.google.com/accounts/o8/id?id=AItOawnXlmnJKsPulm2S_hwwRm3Ky27Zyf-wKMw"
 nickname="Chad"
 subject="Pulling *.flac files as well... too much data"
 date="2013-12-31T19:26:36Z"
 content="""
I've tried setting up my own phone in a similar manner. Unfortunately for me, I store my `*.flac` files in the same location as my `*.mp3` files. For obvious reasons, I do not want to copy these up to my phone. This, however, is not working for me.

    content PHONEUID = ((exclude=*/archive/* and exclude=archive/*) or (not (copies=archive:1 or copies=smallarchive:1))) and (include=keepass/* or include=Books/* or present) and (include=Music/* and exclude=Music/*.flac and exclude=Music/*/*.flac)

I still get `*.flac` files in the repo.
"""]]


code:
[[todo/wishlist: an "assistant" for web-browsing -- tracking the sources of the downloads]] suggests using git-annex as a tool to store downloads tied
to their URLs. This also enables people to have their files stored offline,
while being able to git annex drop them at any time and redownload them
with git annex get. Additionally, a clone of the repo can be used to
download whatever files are desired from online.

This tip explains how to implement a similar system to the one described in
the linked wishlist with existing software and features of git-annex.

The first step is to install the Firefox plugin
[FlashGot](http://flashgot.net/). We will use it to provide the Firefox
shortcuts to add things to our annex.

We also need a normal download manager, if we want to get status updates as
the download is done. We'll need to configure git-annex to use it by
setting `annex.web-download-command` as Joey describes in his comment on
[[todo/wishlist: allow configuration of downloader for addurl]]. See the
manpage [[git-annex]] for more information on setting configuration.

Once we have installed all that, we need a script that has an interface
which FlashGot can treat as a downloader, but which calls git-annex to do
the actual downloading. Such a script is available from
<https://gist.github.com/andyg0808/5342434>. Download it and store it
somewhere it can live, or cut and paste:

[[!format sh """
#!/bin/bash
# $1=folder to cd to (must be a git annex repo)
# $2=URL to download

cd "$1"
git-annex addurl "$2"
"""]]

Finally, we need to configure FlashGot to use the script as a downloader.
Go to Tools > Add-ons in Firefox. Click "Preferences" on FlashGot. Click
the Add button next to the list of download managers. Enter a name for the
git-annex downloader. Choose the script that was downloaded from the
"Locate executable file" dialog that appears. Now set the command line
arguments template to be "[FOLDER] [URL]" (you can find more substitution
expressions in the Placeholders dropdown above the Command line arguments
template field). You're done!

Go ahead and test it by trying to download a file using FlashGot. It should
offer as one of its available download managers the new manager you created
just above. Select it and have fun!


code:
[[!comment format=mdwn
 username="http://joeyh.name/"
 nickname="joey"
 subject="comment 1"
 date="2013-04-11T20:16:02Z"
 content="""
As of my last commit, you don't really need a separate download manager. The webapp will now display urls that `git annex addurl` is downloading in among the other transfers.
"""]]


code:
ZSH users, here's some good news: after 2 years of silence, the completion function for git-annex has been updated. It now supports *all* git-annex commands (as of 5.20140517) and has many improvements for completing arguments, remotes, groups, and backends.

To install it:

1. make sure your have Python 3 installed (as `python3` somewhere in your `$PATH`; tested with 3.4, should work with 3.2+)
2. get it from [GitHub](https://github.com/Schnouki/git-annex-zsh-completion)
3. copy `_git-annex` to somewhere in your `$fpath` (I use `$HOME/.config/zsh/completion`)
4. run `autoload -U path/to/_git-annex`
5. type `git annex <TAB>`

This is very far from being perfect, but it's (IMHO) better than nothing. If you have any issue or suggestion, please [tell me](https://github.com/Schnouki/git-annex-zsh-completion/issues)!

Many thanks to Frank Terbeck and Valentin Haenel, the original authors of this completion function ([source](https://github.com/esc/git-annex-zsh-completion)).


code:
[[!meta title="using assume-unstages to speed up git with large trees of annexed files"]]

Git update-index's assume-unstaged feature can be used to speed
up `git status` and stuff by not statting the whole tree looking for changed
files.

This feature works quite well with git-annex. Especially because git
annex's files are immutable, so aren't going to change out from under it,
this is a nice fit. If you have a very large tree and `git status` is
annoyingly slow, you can turn it on:

	git config core.ignoreStat true

When `git mv` and `git rm` are used, those changes *do* get noticed, even
on assume-unchanged files. When new files are added, eg by `git annex add`,
they are also noticed.

There are two gotchas. Both occur because `git add` does not stage
assume-unchanged files.

1. When an annexed file is moved to a different directory, it updates
   the symlink, and runs `git add` on it. So the file will move,
   but the changed symlink will not be noticed by git and it will commit a
   dangling symlink.
2. When using `git annex migrate`, it changes the symlink and `git adds`
   it. Again this won't be committed.

These can be worked around by running `git update-index --really-refresh`
after performing such operations. I hope that `git add` will be changed
to stage changes to assume-unchanged files, which would remove this
only complication. --[[Joey]]


code:
[[!comment format=mdwn
 username="https://me.yahoo.com/a/2djv2EYwk43rfJIAQXjYt_vfuOU-#a11a6"
 nickname="Olivier R"
 subject="It doesn't work 100%"
 date="2012-05-03T21:42:54Z"
 content="""
When you remove tracked files... it doesn't show the new status. it's like if the file was ignored.

"""]]


code:
[[!comment format=mdwn
 username="https://www.google.com/accounts/o8/id?id=AItOawnxlx1UrzVhdy6_gFjzmF42x6QXxBUxg00"
 nickname="Jakukyo"
 subject="comment 2"
 date="2013-09-05T12:14:42Z"
 content="""
> There are two gotchas...

So just always run `git annex add` after editing a file
and `git update-index --really-refresh` after migrating
backend?

"""]]


code:
git-annex's [[metadata]] works best when files have a lot of useful
metadata attached to them.

To make git-annex automatically set the year and month when adding files,
run `git config annex.genmetadata true`.

A git commit hook can be set up to extract lots of metadata from files
like photos, mp3s, etc.

1. Install the `extract` utility, from <http://www.gnu.org/software/libextractor/>
   `apt-get install extract`
2. Download [[pre-commit-annex]] and install it in your git-annex repository
   as `.git/hooks/pre-commit-annex`.
   Remember to make the script executable!
3. Run: `git config metadata.extract "artist album title camera_make video_dimensions"`

Now any fields you list in metadata.extract to will be extracted and
stored when files are committed.

To get a list of all possible fields, run: `extract -L | sed 's/ /_/g'`

By default, if a git-annex already has a metadata field for a file,
its value will not be overwritten with metadata taken from files.
To allow overwriting, run: `git config metadata.overwrite true`


code:
[[!comment format=mdwn
 username="https://www.google.com/accounts/o8/id?id=AItOawkSq2FDpK2n66QRUxtqqdbyDuwgbQmUWus"
 nickname="Jimmy"
 subject="comment 1"
 date="2014-03-03T07:44:29Z"
 content="""
http://projects.iq.harvard.edu/fits might be an even better choice than libextractor. We use it in work and its not too bad, but it can be slow to startup due to the JVM.
"""]]


code:
[[!comment format=mdwn
 username="https://id.koumbit.net/anarcat"
 ip="2001:1928:1:9::1"
 subject="comment 2"
 date="2014-04-01T04:18:10Z"
 content="""
is there a way for this to be done globally, without having to install and configure the hook for each repository? it seems like a fairly useful feature that could be factored in git-annex itself (as opposed to be shipped as a shell script)...

also, is there a way to retroactively parse the tags from existing files (as opposed to only new files added to the repo).

thanks
"""]]


code:
[[!comment format=mdwn
 username="http://joeyh.name/"
 ip="209.250.56.191"
 subject="comment 3"
 date="2014-04-17T20:15:07Z"
 content="""
@anarcat, I have modified [[pre-commit-annex]] so if it's passed already annexed files, it'll extract their metadata.

So this can be used to add metadata to files added before you installed the hook, or if you've configured more fields to be extracted.
"""]]


code:
#!/bin/sh
#
# This script can be used to add git-annex metadata to files when they're
# committed. It is typically installed as .git/hooks/pre-commit-annex
#
# You can also run this script by hand, passing it the names of files
# already checked into git-annex, and it will extract/refresh the git-annex
# metadata from the files.
#
# Copyright 2014 Joey Hess <id@joeyh.name>
# License: GPL-3+

extract="$(git config metadata.extract || true)"
want="$(perl -e 'print (join("|", map {s/_/ /g; "^$_ - "} (split " ", shift())))' "$extract")"

if [ -z "$want" ]; then
	exit 0
fi

case "$(git config --bool metadata.overwrite || true)" in
	true)
		overwrite=1
	;;
	*)
		overwrite=""
	;;
esac

addmeta () {
	file="$1"
	field="$2"
	value="$3"
	afield="$(echo "$field" | tr ' ' _)"
	if [ "$overwrite" ]; then
		p="$afield=$value"

	else
		p="$afield?=$value"
	fi
	git -c annex.alwayscommit=false annex metadata "$file" -s "$p" --quiet
}

if git rev-parse --verify HEAD >/dev/null 2>&1; then
	against=HEAD
else
	# Initial commit: diff against an empty tree object
	against=4b825dc642cb6eb9a060e54bf8d69288fbee4904
fi

IFS="
"

process () {
	if [ -e "$f" ]; then
		for l in $(extract "$f" | egrep "$want"); do
			field="${l%% - *}"
			value="${l#* - }"
			addmeta "$f" "$field" "$value"
		done
	fi
}

if [ -n "$*" ]; then
	for f in $@; do
		process "$f"
	done
else
	for f in $(git diff-index --name-only --cached $against); do
		process "$f"
	done
fi


code:
Normally git-annex does not retrieve file contents when checking out a
tree. In some use cases, it makes sense to always have the contents of
files available after a `git checkout` or `git update`. This can be
accomplished by installing the following as `.git/hooks/post-checkout`

	#!/bin/sh
	# Uses git-annex to get all files in the specified directories
	# (relative to the top of the repository) on checkout.
	dirs=.
	top="$(git rev-parse --show-toplevel)"
	for dir in "$dirs"; do git annex get $top/$dir"; done

By default, all files in the whole repository will be made available. The
`dirs` setting can be configured if you only want to get files in certian
directories.


code:
When git annex does fsck on (for example) a GPG-encrypted special directory remote, it first transfers the whole file into .git/annex/tmp directory.
If your annex is on an SSD, it's a good idea to make .git/annex/tmp a symlink to say /var/tmp so SSD isn't worn down.  This actually may be a better default.


code:
[[!comment format=mdwn
 username="https://www.google.com/accounts/o8/id?id=AItOawln3ckqKx0x_xDZMYwa9Q1bn4I06oWjkog"
 nickname="Michael"
 subject="comment 1"
 date="2013-07-31T15:15:41Z"
 content="""
Of course, this only works when /var/tmp isn't on SSD itself.  Perhaps tmpfs (e.g. a /tmp on many distros) is good -- after checking that there's enough space to transfer a particular file.
"""]]


code:
[[!comment format=mdwn
 username="https://www.google.com/accounts/o8/id?id=AItOawln3ckqKx0x_xDZMYwa9Q1bn4I06oWjkog"
 nickname="Michael"
 subject="there's a problem"
 date="2013-08-04T17:15:05Z"
 content="""
If .git/annex/tmp is a symlink to another fs, then adding doesn't work:

    add file1.jpg (checksum...)
    git-annex: /path/to/.git/annex/tmp/tmp30148: rename: unsupported operation (Invalid cross-device link)

It looks like it would be good to have two types of tmp directories here, one for adding, another one for verifying (and that one could be redirected off SSD).

"""]]


code:
[[!comment format=mdwn
 username="guilhem"
 ip="46.239.117.180"
 subject="comment 3"
 date="2013-08-19T01:05:40Z"
 content="""
A nice feature would be to perform the `fsck` on the (encrypted) remote itself, as it would avoid to clutter either the network or the tmpdir. However, that requires some changes in git-annex's backend. Indeed it would no longer be enough to store a single digest per (plain) file: a new digest needs to be stored for each encrypted copy. It is not necessarily a big deal, but the backend would need to be reorganized carefully.
"""]]


code:
If you are starting from nothing (no existing `git` or `git-annex` repository) and want to use a server as a centralised repository, try the following steps.

On the server where you'll hold the "master" repository:

	server$ cd /one/git
	server$ mkdir m
	server$ cd m
	server$ git init --bare
	Initialized empty Git repository in /one/git/m/
	server$ git annex init origin
	init origin ok
	server$

Clone that to the laptop:

	laptop$ cd /other
	laptop$ git clone ssh://server//one/git/m
	Cloning into 'm'...
	remote: Counting objects: 5, done.
	remote: Compressing objects: 100% (3/3), done.
	remote: Total 5 (delta 0), reused 0 (delta 0)
	Receiving objects: 100% (5/5), done.
	warning: remote HEAD refers to nonexistent ref, unable to checkout.

	laptop$ cd m
	laptop$ git annex init laptop
	init laptop ok
        laptop$

Add some content:

	laptop$ git annex addurl http://kitenet.net/~joey/screencasts/git-annex_coding_in_haskell.ogg
	addurl kitenet.net_~joey_screencasts_git-annex_coding_in_haskell.ogg (downloading http://kitenet.net/~joey/screencasts/git-annex_coding_in_haskell.ogg ...) --2011-12-15 08:13:10--  http://kitenet.net/~joey/screencasts/git-annex_coding_in_haskell.ogg
	Resolving kitenet.net (kitenet.net)... 2001:41c8:125:49::10, 80.68.85.49
	Connecting to kitenet.net (kitenet.net)|2001:41c8:125:49::10|:80... connected.
	HTTP request sent, awaiting response... 200 OK
	Length: 39362757 (38M) [audio/ogg]
	Saving to: `/other/m/.git/annex/tmp/URL--http&c%%kitenet.net%~joey%screencasts%git-annex_coding_in_haskell.ogg'

	100%[======================================>] 39,362,757  2.31M/s   in 17s

	2011-12-15 08:13:27 (2.21 MB/s) - `/other/m/.git/annex/tmp/URL--http&c%%kitenet.net%~joey%screencasts%git-annex_coding_in_haskell.ogg' saved [39362757/39362757]

	(checksum...) ok
	(Recording state in git...)

Don't forget to commit it:

	laptop$ git commit -m 'See Joey play.'
	[master (root-commit) 106e923] See Joey play.
	 1 files changed, 1 insertions(+), 0 deletions(-)
	  create mode 120000 kitenet.net_~joey_screencasts_git-annex_coding_in_haskell.ogg
	laptop$

All fine, now push it back to the centralised master:

	laptop$ git push origin master
	Counting objects: 20, done.
	Delta compression using up to 4 threads.
	Compressing objects: 100% (11/11), done.
	Writing objects: 100% (18/18), 1.50 KiB, done.
	Total 18 (delta 1), reused 1 (delta 0)
	To ssh://server//one/git/m
	   3ba1386..ad3bc9e  git-annex -> git-annex
	laptop$

You'll probably want to use `git annex copy --to origin` to copy the
annexed file contents to the server. See the [[walkthrough]] for details.

You can add more "client" repositories by following the `laptop`
sequence of operations.


code:
[[!comment format=mdwn
 username="http://joey.kitenet.net/"
 nickname="joey"
 subject="comment 1"
 date="2011-12-23T19:19:53Z"
 content="""
See also: [[centralized_git_repository_tutorial]]
"""]]


code:
The [[walkthrough]] builds up a decentralized git repository setup, but
git-annex can also be used with a centralized bare repository, just like
git can. This tutorial shows how to set up a centralized repository hosted on
GitHub.

## set up the repository, and make a checkout

I've created a repository for technical talk videos, which you can
[fork on Github](https://github.com/joeyh/techtalks).
Or make your own repository on GitHub (or elsewhere) now.

On your laptop, [[install]] git-annex, and clone the repository:

	# git clone git@github.com:joeyh/techtalks.git
	# cd techtalks

Tell git-annex to use the repository, and describe where this clone is
located:

	# git annex init 'my laptop'
	init my laptop ok

Let's tell git-annex that GitHub doesn't support running git-annex-shell there.
This means you can't store annexed file *contents* on GitHub; it would
really be better to host the bare repository on your own server, which
would not have this limitation. (If you want to do that, check out
[[using_gitolite_with_git-annex]].)

	# git config remote.origin.annex-ignore true

## add files to the repository

Add some files, obtained however.

	# youtube-dl -t 'http://www.youtube.com/watch?v=b9FagOVqxmI'
	# git annex add *.mp4
	add Haskell_Amuse_Bouche-b9FagOVqxmI.mp4 (checksum) ok
	(Recording state in git...)
	# git commit -m "added a video. I have not watched it yet but it sounds interesting"

This file is available directly from the web; so git-annex can download it:

	# git annex addurl http://kitenet.net/~joey/screencasts/git-annex_coding_in_haskell.ogg
	addurl kitenet.net_~joey_screencasts_git-annex_coding_in_haskell.ogg
	(downloading http://kitenet.net/~joey/screencasts/git-annex_coding_in_haskell.ogg ...)
	(checksum...) ok
	(Recording state in git...)
	# git commit -a -m 'added a screencast I made'

Feel free the rename the files, etc, using normal git commands:

	# git mv Haskell_Amuse_Bouche-b9FagOVqxmI.mp4 Haskell_Amuse_Bouche.mp4
	# git mv kitenet.net_~joey_screencasts_git-annex_coding_in_haskell.ogg git-annex_coding_in_haskell.ogg
	# git commit -m 'better filenames'

Now push your changes back to the central repository. This first time,
remember to push the git-annex branch, which is used to track the file
contents.

	# git push origin master git-annex
	To git@github.com:joeyh/techtalks.git
	 * [new branch]      master -> master
	 * [new branch]      git-annex -> git-annex

That push went fast, because it didn't upload large videos to GitHub.
To check this, you can ask git-annex where the contents of the videos are:

	# git annex whereis
	whereis Haskell_Amuse_Bouche.mp4 (1 copy)
	  	767e8558-0955-11e1-be83-cbbeaab7fff8 -- here
	ok
	whereis git-annex_coding_in_haskell.ogg (2 copies)
	  	00000000-0000-0000-0000-000000000001 -- web
	   	767e8558-0955-11e1-be83-cbbeaab7fff8 -- here
	ok

## make more checkouts

So far you have a central repository, and a checkout on a laptop.
Let's make another checkout that's used as a backup. You can put it anywhere
you like, just make it be somewhere your laptop can access. A few options:

* Put it on a USB drive that you can plug into the laptop.
* Put it on a desktop.
* Put it on some server in the local network.
* Put it on a remote VPS.

I'll use the VPS option, but these instructions should work for
any of the above.

	# ssh server
	server# sudo apt-get install git-annex

Clone the central repository as before. (If the clone fails, you need
to add your server's ssh public key to github -- see
[this page](http://help.github.com/ssh-issues/).)

	server# git clone git@github.com:joeyh/techtalks.git
	server# cd techtalks
	server# git config remote.origin.annex-ignore true
	server# git annex init 'backup'
	init backup (merging origin/git-annex into git-annex...) ok

Notice that the server does not have the contents of any of the files yet.
If you run `ls`, you'll see broken symlinks. We want to populate this
backup with the file contents, by copying them from your laptop.

Back on your laptop, you need to configure a git remote for the backup.
Adjust the ssh url as needed to point to wherever the backup is. (If it
was on a local USB drive, you'd use the path to the repository instead.)

	# git remote add backup ssh://server/~/techtalks

Now git-annex on your laptop knows how to reach the backup repository,
and can do things like copy files to it:

	# git annex copy --to backup git-annex_coding_in_haskell.ogg
	copy git-annex_coding_in_haskell.ogg (checking backup...)
	12877824   2%  255.11kB/s    00:00
	ok

You can also `git annex move` files to it, to free up space on your laptop.
And then you can `git annex get` files back to your laptop later on, as
desired.

After you use git-annex to move files around, remember to push,
which will broadcast its updated location information.

	# git push

## take it farther

Of course you can create as many checkouts as you desire. If you have a
desktop machine too, you can make a checkout there, and use `git remote
add` to also let your desktop access the backup repository.

You can add remotes for each direct connection between machines you find you
need -- so make the laptop have the desktop as a remote, and the desktop
have the laptop as a remote, and then on either machine git-annex can
access files stored on the other.


code:
[[!comment format=mdwn
 username="https://www.google.com/accounts/o8/id?id=AItOawkC0W3ZQERUaTkHoks6k68Tsp1tz510nGo"
 nickname="Georg"
 subject="sync, push, pull with/to/from centralized bare repository"
 date="2013-10-07T06:45:19Z"
 content="""
Hi Joey,

thanks for tutorial with the centralized repo. I am currently trying to set up a central bare repo for two clients (they cannot communicate directly with each other). I am not sure if I am pushing/pulling the right way.

On the server I did:

    git init --bare
    git annex init origin

On Cĺient Alice (I want to give Bob a chance get call \"git annex get\" from \"origin\"):

    git clone ssh://tktest@192.168.56.104/~/annex .
    git annex init Alice
    git annex merge
    git annex add .
    git commit -a -m \"Added tutorial\"
    git push origin master git-annex
    git annex copy . --to origin

On Client Bob I have called \"clone, init, merge, add, push, copy\" also.

Now the tricky part - do I have to call \"git annex sync\" at Alice's side to get the updates from Bob over origin?
I ran into troubles if I called \"copy --to origin\" before \"git push origin master git-annex\". How can I resolve a non-fast-forware on the git-annex branch?
Some notes about how to sync over a central bare repo would be nice here =)

Thanks a lot, Georg
"""]]


code:
[[!comment format=mdwn
 username="http://joeyh.name/"
 ip="4.153.253.80"
 subject="How can I resolve a non-fast-forware on the git-annex branch?"
 date="2013-10-07T17:08:32Z"
 content="""
By either running `git annex sync`, or if you want to pull and push yourself, by running `git annex merge` before pushing.
"""]]


code:
You can use git-annex as a podcatcher, to download podcast contents.
No additional software is required, but your git-annex must be built
with the Feeds feature (run `git annex version` to check).

All you need to do is put something like this in a cron job:

`cd somerepo && git annex importfeed http://url/to/podcast http://other/podcast/url`

This downloads the urls, and parses them as RSS, Atom, or RDF feeds.
All enclosures are downloaded and added to the repository, the same as if you
had manually run `git annex addurl` on each of them.

git-annex will avoid downloading a file from a feed if its url has already
been stored in the repository before. So once a file is downloaded,
you can move it around, delete it, `git annex drop` its content, etc,
and it will not be downloaded again by repeated runs of
`git annex importfeed`. Just how a podcatcher should behave.

## templates

To control the filenames used for items downloaded from a feed,
there's a --template option. The default is
`--template='${feedtitle}/${itemtitle}${extension}'`

Other available template variables:
feedauthor, itemauthor, itemsummary, itemdescription, itemrights, itemid,
itempubdate, author, title.

## catching up

To catch up on a feed without downloading its contents,
use `git annex importfeed --relaxed`, and delete the symlinks it creates.
Next time you run `git annex addurl` it will only fetch any new items.

## fast mode

To add a feed without downloading its contents right now,
use `git annex importfeed --fast`. Then you can use `git annex get` as
usual to download the content of an item.

## storing the podcast list in git

You can check the list of podcast urls into git right next to the
files it downloads. Just make a file named feeds and add one podcast url
per line.

Then you can run git-annex on all the feeds:

`xargs git-annex importfeed < feeds`

## distributed podcatching

A nice benefit of using git-annex as a podcatcher is that you can
run `git annex importfeed` on the same url in different clones
of a repository, and `git annex sync` will sync it all up.

## centralized podcatching

You can also have a designated machine which always fetches all podcstas
to local disk and stores them. That way, you can archive podcasts with
time-delayed deletion of upstream content. You can also work around slow
downloads upstream by podcatching to a server with ample bandwidth or work
around a slow local Internet connection by podcatching to your home server
and transferring to your laptop on demand.

## youtube playlists

If your git-annex is also built with quvi support, you can also use
`git annex importfeed` on youtube playlists. It will automatically download
the videos linked to by the playlist.

## metadata

As well as storing the urls for items imported from a feed, git-annex can
store additional [[metadata]], like the author, and itemdescription.
This can then be looked up later, used in [[metadata_driven_views]], etc.

To make all available metadata from the feed be stored:
`git config annex.genmetadata true`


code:
[[!comment format=mdwn
 username="http://joeyh.name/"
 ip="2001:4978:f:21a::2"
 subject="comment 10"
 date="2013-08-05T16:47:30Z"
 content="""
`cabal install feed` should get the necessary library installed so that git-annex will build with feeds support.
"""]]


code:
[[!comment format=mdwn
 username="http://a-or-b.myopenid.com/"
 ip="220.244.41.108"
 subject="comment 11"
 date="2013-08-06T04:20:16Z"
 content="""
    $ cabal install feed
    Resolving dependencies...
    All the requested packages are already installed:
    feed-0.3.9.1
    Use --reinstall if you want to reinstall anyway.

Then I reinstalled `git-annex` but it still doesn't find the feeds flag.

    $ git annex version
    git-annex version: 4.20130802
    build flags: Assistant Webapp Pairing Testsuite S3 WebDAV FsEvents XMPP DNS

Do I need to do something like:

    cabal install git-annex --bindir=$HOME/bin -f\"-assistant -webapp -webdav -pairing -xmpp -dns -feed\"

...but what are the default flags to include in addition to `-feed`
"""]]


code:
[[!comment format=mdwn
 username="http://joeyh.name/"
 ip="2001:4978:f:21a::2"
 subject="comment 12"
 date="2013-08-06T04:24:10Z"
 content="""
-f-Feed will disable the feature. -fFeed will try to force it on.

You can probably work out what's going wrong using cabal install -v3
"""]]


code:
[[!comment format=mdwn
 username="http://a-or-b.myopenid.com/"
 ip="220.244.41.108"
 subject="comment 13"
 date="2013-08-06T05:42:45Z"
 content="""
So I ran `cabal install -v3` and looked at the output,

    Flags chosen: feed=True, tdfa=True, testsuite=True, android=False,
    production=True, dns=True, xmpp=True, pairing=True, webapp=True,
    assistant=True, dbus=True, inotify=True, webdav=True, s3=True

This looks like feed should be on.

There doesn't appear to be any errors in the compile either.

Is it as simple as a bug where this flag just doesn't show in the `git annex version` command?
"""]]


code:
[[!comment format=mdwn
 username="http://joeyh.name/"
 ip="2001:4978:f:21a::2"
 subject="comment 14"
 date="2013-08-07T16:03:12Z"
 content="""
Yes, it did turn out to be as simple as my having forgotten that I have to manually add features to the version list.
"""]]


code:
[[!comment format=mdwn
 username="http://23.gs/"
 ip="46.165.197.5"
 subject="No file extension?"
 date="2013-08-12T13:21:50Z"
 content="""
It seems git-annex is a bit overzealous when sanitizing the file extension, currently I get: \"Nerdkunde/Let_s_go_to_the_D_M_C_A_m4a\" from http://www.nerdkunde.de/episodes.m4a.rss with the default template and only \"Nerdkunde/Let_s_go_to_the_D_M_C_A._m4a\" if I add the \".\" in the template myself...
"""]]


code:
[[!comment format=mdwn
 username="arand"
 ip="130.243.226.21"
 subject="comment 16"
 date="2013-08-12T13:32:46Z"
 content="""
The filename extension is a known issue and already fixed in the development version, see <http://git-annex.branchable.com/bugs/importfeed_uses___34____95__foo__34___as_extension/>
"""]]


code:
[[!comment format=mdwn
 username="https://www.google.com/accounts/o8/id?id=AItOawlpKmTa1OPwy5Jk24pOoD8Vlo2jahzTPnw"
 nickname="Stephen"
 subject="rss authentication"
 date="2013-08-13T13:32:52Z"
 content="""
If a podcast requires authentication, is there a way to pass credentials through? I tried `http://user:pass@site.com/rss.xml` but it didn't work.

"""]]


code:
[[!comment format=mdwn
 username="http://www.joachim-breitner.de/"
 nickname="nomeata"
 subject="--fast and --relaxed"
 date="2013-08-16T07:27:59Z"
 content="""
Hi,

the explanations to --fast and --relaxed on this page could be extended a bit. I looked it up in the man page, but it is not yet clear to me when I would use one or the other with feeds. Also, does “Next time you run git annex addurl it will only fetch any new items.” really only apply to --relaxed, and not --fast?

Furthermore, it would be good if there were a template variable `itemnum` that I can use to ensure that `ls` prints the casts in the right order, even when the titles of the items are not helpful.

Greetings,
Joachim
"""]]


code:
[[!comment format=mdwn
 username="http://joeyh.name/"
 ip="4.154.0.63"
 subject="comment 19"
 date="2013-08-22T15:25:02Z"
 content="""
I would expect user:pass@site.com to work if the site is using http basic auth. `importfeed` just runs `wget` (or `curl`) to do all downloads, and wget's documentation says that works. It also says you can use ~/.netrc to store the password for a site.
"""]]


code:
[[!comment format=mdwn
 username="ckeen"
 ip="79.249.110.228"
 subject="Filename too long"
 date="2013-07-30T14:39:44Z"
 content="""
It seems that some of my feeds get stored into keys that generate a too long filename:

    podcasts/.git/annex/tmp/b1f_325_URL-s143660317--http&c%%feedproxy.google.com%~r%mixotic%~5%urTIRWQK2OQ%Mixotic__258__-__Michael__Miller__-__Galactic__Technolgies.mp3.log.web:
    openBinaryFile: invalid argument (File name too long)

Is there a way to work around this?
"""]]


code:
[[!comment format=mdwn
 username="http://joeyh.name/"
 ip="4.154.0.63"
 subject="comment 20"
 date="2013-08-22T15:29:11Z"
 content="""
The git-annex man page has a bit more to say about --relaxed and --fast. Their behavior when used with `importfeed` is the same as with `addurl`.

If the podcast feed provides an `itemid`, you can use that in the filename template. I don't know how common that is. Due to the way `importfeed` works, it cannot keep track of eg, an incrementing item number itself.
"""]]


code:
[[!comment format=mdwn
 username="Sazius"
 ip="62.78.213.233"
 subject="comment 21"
 date="2014-07-01T20:52:06Z"
 content="""
For some podcast feeds I typically wish to view the description of the show before I decide to download it or not. Is there some way to perform that use case using git annex? I know `itemdescription` is something I can include in the template for the filename, but the descriptions can be really long... doesn't seem very elegant to have that in the file name. Could the description for example be included as metadata of the item?
"""]]


code:
[[!comment format=mdwn
 username="http://joeyh.name/"
 ip="209.250.56.55"
 subject="metadata"
 date="2014-07-03T18:25:32Z"
 content="""
Good idea, Sazius!

I've made importfeed store the metadata, as long as annex.genmetadata is set in .git/config.
"""]]


code:
[[!comment format=mdwn
 username="http://joeyh.name/"
 ip="4.154.0.21"
 subject="comment 2"
 date="2013-07-30T17:16:07Z"
 content="""
@ckeen You seem to be using a filesystem that does not support filenames 150 characters long. This is unusual -- even windows and android can support a filename up to 255 characters in length. `git-annex addurl` already deals with this sort of problem by limiting the filename to 255 characters. If you'd like to file a bug report with details about your system, I can try to make git-annex support its limitations, I suppose.
"""]]


code:
[[!comment format=mdwn
 username="http://www.joachim-breitner.de/"
 nickname="nomeata"
 subject="Great stuff!"
 date="2013-07-30T21:21:57Z"
 content="""
Looking forward to seeing it in Debian unstable; where it will definitely replace my hpodder setup.

I guess there is no easy way to re-use the files already downloaded with hpodder? At first I thought that `git annex importfeed --relaxed` followed by adding the files to the git annex would work, but `importfeed` stores URLs, not content-based hashes, so it wouldn’t match up.
"""]]


code:
[[!comment format=mdwn
 username="http://joeyh.name/"
 ip="4.154.0.21"
 subject="comment 4"
 date="2013-07-30T21:29:50Z"
 content="""
@nomeata, well, you can, but it has to download the files again.

When run without --fast, `importfeed` does use content based hashes, so if you run it in a temporary directory, it will download the content redundantly, hash it and see it's the same, and add the url to that hash. You can then delete the temporary directory, and the files hpodder had downloaded will have the url attached to them now. I don't know if this really buys you anything over deleting the hpodder files and starting over though.
"""]]


code:
[[!comment format=mdwn
 username="ckeen"
 ip="79.249.110.228"
 subject="Force a reload of a feed?"
 date="2013-07-31T10:35:50Z"
 content="""
Currently I have my podcasts imported with --fast. For some reason there are podcast episodes missing. This has been done propably during my period of toying with the feature. If I retry on a clean annex I see all episodes. My suspicion is that git-annex has been interrupted during downloading a feed but now somehow thinks it's already there. How can I debug this situation and/or force git annex to retry all the links in a feed?
"""]]


code:
[[!comment format=mdwn
 username="http://joeyh.name/"
 ip="4.154.0.21"
 subject="use the force"
 date="2013-07-31T16:20:39Z"
 content="""
The only way it can skip downloading a file is if its url has already been seen before. Perhaps you deleted them?

I've made `importfeed --force` re-download files it's seen before.
"""]]


code:
[[!comment format=mdwn
 username="ckeen"
 ip="78.108.63.46"
 subject="--force reload all URLs"
 date="2013-08-01T09:47:34Z"
 content="""
Is it intentionally saving URLs with a prefixed 2_? I have sorted out all missing URLs and renamed it, so no harm done, but it has been a bit of a hassle to get there.
"""]]


code:
[[!comment format=mdwn
 username="http://joeyh.name/"
 ip="4.152.108.145"
 subject="comment 8"
 date="2013-08-01T16:05:10Z"
 content="""
I've now made importfeed --force a bit smarter about reusing existing files.
"""]]


code:
[[!comment format=mdwn
 username="http://a-or-b.myopenid.com/"
 ip="220.244.41.108"
 subject="How do I switch on the 'feeds' feature?"
 date="2013-08-05T04:52:41Z"
 content="""
Joey - your initial post said:

    git-annex must be built with the Feeds feature (run git annex version to check).

...but how do I actually switch on the feeds feature?

I install git-annex from cabal, so I do

    cabal update
    cabal install git-annex

which I did this morning and now `git annex version` gives me:

    git-annex version: 4.20130802
    build flags: Assistant Webapp Pairing Testsuite S3 WebDAV FsEvents XMPP DNS

So it is the latest version, but without Feeds.  :-(
"""]]


code:
dropboxannex 0.2.0
=========

Hook program for gitannex to use dropbox as backend

# Requirements:

    python2
    python-pkg-resources

Credit for the Dropbox api interface goes to Dropbox.

# Install
Clone the git repository in your home folder.

    git clone git://github.com/TobiasTheViking/dropboxannex.git

This should make a ~/dropboxannex folder

# Setup
Make the file executable, and link it into PATH

    cd ~/dropboxannex; chmod +x git-annex-remote-dropbox; sudo ln -sf `pwd`/git-annex-remote-dropbox /usr/local/bin/git-annex-remote-dropbox

# Commands for gitannex:

    git annex initremote dropbox type=external externaltype=dropbox encryption=shared folder=gitannex
    git annex describe dropbox "the dropbox library"


code:
bergey has developed an emacs mode for browsing git-annex repositories,
dired style.

<https://gitorious.org/emacs-contrib/annex-mode>

Locally available files are colored differently, and pressing g runs
`git annex get` on the file at point.

----

John Wiegley has developed a brand new git-annex interaction mode for
Emacs, which aims to integrate with the standard facilities
(C-x C-q, M-x dired, etc) rather than invent its own interface.

<https://github.com/jwiegley/git-annex-el>

He has also added support to org-attach; if
`org-attach-git-annex-cutoff' is non-nil and smaller than the size
 of the file you're attaching then org-attach will `git annex add the
file`; otherwise it will "git add" it.

----

[magit-annex](https://github.com/kyleam/magit-annex) adds magit support
for a few features, including adding files and syncing.