X-Git-Url: https://git.distorted.org.uk/~mdw/stgit/blobdiff_plain/9564af74822b276d435319fc271eda591e5125a6..6a458ad8d2507418f4709c0b25c0d718ba6210a4:/Documentation/tutorial.txt diff --git a/Documentation/tutorial.txt b/Documentation/tutorial.txt index 6eaa623..7484d70 100644 --- a/Documentation/tutorial.txt +++ b/Documentation/tutorial.txt @@ -1,414 +1,834 @@ -StGIT Tutorial +StGit tutorial ############## +StGit is a command-line application that provides functionality +similar to link:http://savannah.nongnu.org/projects/quilt/[Quilt] +(i.e. pushing/popping patches to/from a stack), but using Git instead +of +diff+ and +patch+. StGit stores its patches in a Git repository as +normal Git commits, and provides a number of commands to manipulate +them in various ways. -StGIT is a Python application that provides functionality similar to -quilt (i.e. pushing/popping patches to/from a stack) using GIT instead -of 'diff' and 'patch'. StGIT stores its patches in a GIT repository as -normal GIT commit objects. -StGIT is not an SCM interface on top of GIT. For standard SCM -operations, either use GIT's porcelain commands or the Cogito tool. -StGIT is available for download at http://www.procode.org/stgit/ . -This tutorial assumes you are already familiar with GIT. For more -information on GIT, see the GIT_tutorial or git(7) . +This tutorial assumes you are already familiar with the basics of Git +(for example, branches, commits, and conflicts). For more information +on Git, see linkman:git[1] or link:http://git.or.cz/[the Git home +page]. -Basic Operation +Help +==== + +For a full list of StGit commands: + + $ stg help + +For quick help on individual subcommands: + + $ stg help + +For more extensive help on a subcommand: + + $ man stg- + +(The documentation is also available in link:stg.html[HTML +format].) + + +Getting started =============== -Help ----- +StGit is not a stand-alone program -- it operates on a Git repository +that you have already created, using +git init+ or +git clone+. So get +one of those; if you don't have one at hand, try for example + + $ git clone git://repo.or.cz/stgit.git + $ cd stgit + +Before you can create StGit patches, you have to run linkstg:init[]: + + $ stg init + +This initializes the StGit metadata for the current branch. (So if you +want to have StGit patches in another branch too, you need to run +stg +init+ again in that branch.) + +NOTE: As a shortcut, linkstg:clone[] will run +git clone+ followed by ++stg init+ for you. + + +Creating a patch +---------------- + +Now we're ready to create our first patch: + + $ stg new my-first-patch + +This will create a patch called +my-first-patch+, and open an editor +to let you edit the patch's commit message. (If you don't give a name +on the command line, StGit will make one up based on the first line of +the commit message.) This patch is empty, as linkstg:show[] will tell +you: + + $ stg show + +But it won't stay that way for long! Open one of the files in your +favorite text editor, change something, and save. You now have some +local changes in your tree: + + $ stg status + M stgit/main.py + +Then linkstgsub:refresh[] the patch: + + $ stg refresh + +And voilà -- the patch is no longer empty: + + $ stg show + commit 3de32068c600d40d8af2a9cf1f1c762570ae9610 + Author: Audrey U. Thor + Date: Sat Oct 4 16:10:54 2008 +0200 + + Tell the world that I've made a patch + + diff --git a/stgit/main.py b/stgit/main.py + index e324179..6398958 100644 + --- a/stgit/main.py + +++ b/stgit/main.py + @@ -171,6 +171,7 @@ def _main(): + sys.exit(ret or utils.STGIT_SUCCESS) + + def main(): + + print 'My first patch!' + try: + _main() + finally: + +(I'm assuming you're already familiar with +link:http://en.wikipedia.org/wiki/Diff#Unified_format[unified +diff] patches like this from Git, but it's really quite simple; in +this example, I've added the +$$print 'My first patch!'$$+ line to the +file +stgit/main.py+, at around line 171.) + +Since the patch is also a regular Git commit, you can also look at it +with regular Git tools such as linkman:gitk[]. + +Creating another patch +---------------------- + +We want to make another improvement, so let's create a new patch for +it: + + $ echo 'Audrey U. Thor' > AUTHORS + $ stg new credit --message 'Give me some credit' + $ stg refresh + +Note that we can give the commit message on the command line, and that +it doesn't matter whether we run linkstg:new[] before or after we edit +the files. + +So now we have two patches: + + $ stg series --description + + my-first-patch # This is my first patch + > credit # Give me some credit + +linkstg:series[] lists the patches from bottom to top; +$$+$$+ means +that a patch is 'applied', and +>+ that it is the 'current', or +topmost, patch. + +If we want to make further changes to the topmost patch, we just edit +the files and run +stg refresh+. But what if we wanted to change ++my-first-patch+? The simplest way is to linkstgsub:pop[] the +credit+ +patch, so that +my-first-patch+ becomes topmost again: + + $ stg pop credit + Checking for changes in the working directory ... done + Popping patch "credit" ... done + Now at patch "my-first-patch" + $ stg series --description + > my-first-patch # This is my first patch + - credit # Give me some credit + +linkstg:series[] now shows that +my-first-patch+ is topmost again, +which means that linkstg:refresh[] will update it with any changes we +make. + +The minus sign says that +credit+ is 'unapplied' -- this means that +it's been temporarily put aside. If you look at the +AUTHORS+ file, +you'll see that our change to it is gone; and tools such as +linkman:gitk[] will not show it, because it's been edited out of the +Git history. But it's just one linkstg:push[] command away from being +restored: -For a full list of StGIT commands: + $ stg push credit + Checking for changes in the working directory ... done + Fast-forwarded patch "credit" + Now at patch "credit" - stg help +NOTE: You can omit the patch name argument to linkstg:push[] and +linkstg:pop[]. If you do, you will push the next unapplied patch, and +pop the topmost patch, respectively. -For help on individual subcommands: +NOTE: There are at least two more ways to update a non-topmost patch. +One is to use linkstg:refresh[] with the +$$--patch$$+ flag, the other +to create a new patch for the update and then merge it into the other +patch with linkstg:squash[]. - stg (-h | --help) +Keeping commit messages up to date +---------------------------------- + +Since StGit is all about creating readable Git history (or a readable +patch series, which is essentially the same thing), one thing you'll +want to pay attention to is the commit messages of your patches. +linkstg:new[] asks you for a commit message when you create a new +patch, but as time goes by and you refresh the patch again and again, +chances are that the original commit message isn't quite correct +anymore. Fortunately, editing the commit message is very easy: + + $ stg edit + +In addition to linkstg:edit[], you can also give the +$$--edit$$+ flag +to linkstg:refresh[] -- that way, you get to change the commit message +and update the patch at the same time. Use whichever feels most +natural to you. + +NOTE: linkstg:edit[] has a +$$--diff$$+ flag, which gives you the diff +text and not just the commit message in your editor. Be aware, though, +that if you change the diff so that it no longer applies, the edit +will be saved to a file instead of being carried out. If you're not +comfortable editing diffs, just treat +$$--diff$$+ as a way to get to +'see' the diff while you edit the commit message. + +If the patch changes considerably, it might even deserve a new name. +linkstg:rename[] is your friend there. -Repository initialisation -------------------------- -In stand-alone mode, StGIT is used in conjunction with a GIT repository -that is already initialised (using 'git-init-db'). StGIT cannot be used -outside of a GIT repository. -Any branch in a GIT repository may be managed by StGIT. Each branch -managed by StGIT contains an independent series of StGIT patches. -To initialise an existing GIT branch to be managed by StGIT, cd into the -top of your GIT repository, check out the branch you'd like to manage -with StGIT, and type: +Conflicts +--------- + +Normally, when you pop a patch, change something, and then later push +it again, StGit sorts out everything for you automatically. For +example, let's create two patches that modify different files: + + $ stg clone http://homepage.ntlworld.com/cmarinas/stgit.git stgit + $ cd stgit + $ stg new first --message 'First patch' + $ echo '- Do something' >> TODO + $ stg refresh + $ stg new second --message 'Second patch' + $ echo '- Install something' >> INSTALL + $ stg refresh + +then pop them both: + + $ stg pop --all + +and then push them in the opposite order: + + $ stg push second first + $ stg series + + second + > first + +StGit had no problems reordering these patches for us, since they +didn't touch the same file. But it would have worked just fine even if +they had touched the same file, as long as they didn't change the same +part of the file. But what if they did? Let's find out. + + $ stg pop + Checking for changes in the working directory ... done + Popping patch "first" ... done + Now at patch "second" + $ echo '- Do something else' >> TODO + $ stg refresh + +Now, both patches add a new line at the end of +TODO+. So what happens +when we try to have them both applied? + + $ stg push + Pushing patch "first" ... + CONFLICT (content): Merge conflict in TODO + Error: The merge failed during "push". + Revert the operation with "stg undo". + stg push: 1 conflict(s) + +StGit is telling us that it couldn't figure out how to push +first+ on +top of +second+, now that they both modify +TODO+. We can take a look +at the situation with linkstg:status[]: + + $ stg status + ? TODO.ancestor + ? TODO.current + ? TODO.patched + C TODO + +As we were told by linkstg:push[], the conflict is in the file +TODO+. +(If the patch was bigger and touched multiple files, they would all be +listed here; prefixed with +C+ if they had conflicts, and +M+ if StGit +managed to automatically resolve everything in the file.) + +NOTE: +TODO.ancestor+, +TODO.current+, and +TODO.patched+ are the +three versions of the file that StGit tried to merge. The +.current+ +file is the version before the patch was applied, +.patched+ is the +version in the patch we tried to push, and +.ancestor+ the version +that contains neither of the added lines. + +At this point, we have two options: + + 1. Undo the failed merge with linkstg:undo[]. (Remember to use the + +$$--hard$$+ flag, since the unresolved conflict means the + worktree is not clean.) + + 2. Manually resolve the conflict. + +To resolve the conflict, open +TODO+ in your favorite editor. It ends +like this: + +---------------------------------------------------------------------- +- numeric shortcuts for naming patches near top (eg. +1, -2) +- (config?) parameter for number of patches included by "series -s" +<<<<<<< current:TODO +- Do something else +======= +- Do something +>>>>>>> patched:TODO +---------------------------------------------------------------------- + +The 'conflict markers' +<<<<<<<+, +=======+, and +>>>>>>>+ indicate +which lines were already there (+current+) and which were added by the +patch (+patched+). Edit the file so that it looks like it should; in +this case, we want something like this: + +---------------------------------------------------------------------- +- numeric shortcuts for naming patches near top (eg. +1, -2) +- (config?) parameter for number of patches included by "series -s" +- Do something +- Do something else +---------------------------------------------------------------------- + +Note that ``looks like it should'' includes removing the conflict +markers. + +Now that we've resolved the conflict, we just need to tell StGit about +it: + + $ git add TODO + $ stg status + M TODO + ++TODO+ is listed as being modified, not in conflict. And we know from +before how to deal with modified files: + + $ stg refresh + +The conflict is now resolved. We can see that +first+ now looks a +little different; it no longer adds a line at the end of the file: + + $ stg show + commit 8e3ae5f6fa6e9a5f831353524da5e0b91727338e + Author: Audrey U. Thor + Date: Sun Oct 5 14:43:42 2008 +0200 + + First patch + + diff --git a/TODO b/TODO + index 812d236..4ef3841 100644 + --- a/TODO + +++ b/TODO + @@ -24,4 +24,5 @@ The future, when time allows or if someone else does them: + they have scripts for moving the changes in one to the others) + - numeric shortcuts for naming patches near top (eg. +1, -2) + - (config?) parameter for number of patches included by "series -s" + +- Do something + - Do something else + + +Workflow: Development branch +============================ + +One common use of StGit is to ``polish'' a Git branch before you +publish it for others to see. Such history falsification can often be +a 'good' thing -- when you (or someone else) needs to look at what you +did six months later, you are not really interested in all the false +starts and the steps needed to corect them. What you want is the final +solution, presented in a way that makes it easy to read and +understand. + +Of course, there are limits. Editing the last few days' worth of +history is probably a good idea; editing the last few months' probably +isn't. A rule of thumb might be to not mess with history old enough +that you don't remember the details anymore. And rewriting history +that you have published for others to see (and base their own work on) +usually just makes everyone more confused, not less. + +So, let's take a concrete example. Say that you're hacking on StGit, +and have made several Git commits as your work progressed, with commit +messages such as ``Improve the snarfle cache'', ``Remove debug +printout'', ``New snarfle cache test'', ``Oops, spell function name +correctly'', ``Fix documentation error'', and ``More snarfle cache''. + +Now, this is the actual history, but for obvious reasons, this isn't +the kind of history you'd ideally want to find when you six months +from now try to figure out exactly where that elusive snarfle cache +bug was introduced. So let's turn this into the history we can be +proud of. The first step is to make StGit patches out of all those Git +commits: + + $ stg uncommit --number 6 + Uncommitting 6 patches ... + Now at patch "more-snarfle-cache" + done + $ stg series --description + + improve-the-snarfle-cache # Improve the snarfle cache + + remove-debug-printout # Remove debug printout + + new-snarfle-cache-test # New snarfle cache test + + oops-spell-function-name-corre # Oops, spell function name correctly + + fix-documentation-error # Fix documentation error + > more-snarfle-cache # More snarfle cache + +As you can see, linkstg:uncommit[] adds StGit metadata to the last few +Git commits, turning them into StGit patches so that we can do stuff +with them. + +NOTE: With the +$$--number$$+ flag, linkstg:uncommit[] uncommits that +many commits and generates names for them based on their commit +messages. If you like, you can instead list the patch names you want +on the command line. + +At this point, there are a number of things we could do: + + * Continue developing, and take advantage of e.g. linkstg:goto[] or + +stg refresh $$--patch$$+ to stick updates in the right patch to + begin with. + + * Use e.g. linkstg:float[], linkstg:sink[], linkstg:push[], and + linkstg:pop[] to reorder patches. + + * Use linkstg:squash[] to merge two or more patches into one. + linkstgsub:squash[] pushes and pops so that the patches to be + merged are consecutive and unrelated patches aren't in the way, + then makes one big patch out of the patches to be merged, and + finally pushes the other patches back. ++ +Of course, as always when there is pushing involved, there is the +possibility of conflicts. If a push results in a conflict, the +operation will be halted, and we'll be given the option of either +resolving the conflict or undoing. + +Once we feel that the history is as good as it's going to get, we can +remove the StGit metadata, turning the patches back into regular Git +commits again: + + $ stg commit --all + +TIP: linkstg:commit[] can also commit specific patches (named on the +command line), leaving the rest alone. This can be used to retire +patches as they mature, while keeping the newer and more volatile +patches as patches. + + +Workflow: Tracking branch +========================= + +In the 'Development branch' workflow described above, we didn't have +to worry about other people; we're working on our branch, they are +presumably working on theirs, and when the time comes and we're ready +to publish our branch, we'll probably end up merging our branch with +those other peoples'. That's how Git is designed to work. + +Or rather, one of the ways Git is designed to work. An alternative, +popular in e.g. the Linux kernel community (for which Git was +originally created), is that contributors send their patches by e-mail +to a mailing list. Others read the patches, try them out, and provide +feedback; often, the patch author is asked to send a new and improved +version of the patches. Once the project maintainer is satisfied that +the patches are good, she'll 'apply' them to a branch and publish it. + +StGit is ideally suited for the process of creating patches, mailing +them out for review, revising them, mailing them off again, and +eventually getting them accepted. + + +Getting patches upstream +------------------------ + +We've already covered how to clone a Git repository and start writing +patches. As for the next step, there are two commands you might use to +get patches out of StGit: linkstg:mail[] and linkstg:export[]. +linkstg:export[] will export your patches to a filesystem directory as +one text file per patch, which can be useful if you are going to send +the patches by something other than e-mail. Most of the time, though, +linkstg:mail[] is what you want. + +NOTE: Git comes with tools for sending commits via e-mail. Since StGit +patches are Git commits, you can use the Git tools if you like them +better for some reason. + +NOTE: For exporting single patches -- as opposed to a whole bunch of +them -- you could also use linkstg:show[] or linkstg:diff[]. + +Mailing a patch is as easy as this: + + $ stg mail --to recipient@example.com + +You can list one or more patches, or ranges of patches. Each patch +will be sent as a separate mail, with the first line of the commit +message as subject line. Try mailing patches to yourself to see what +the result looks like. + +NOTE: linkstg:mail[] uses +sendmail+ on your computer to send the +mails. If you don't have +sendmail+ properly set up, you can instruct +it to use any SMTP server with the +$$--smtp-server$$+ flag. + +There are many command-line options to control exactly how mails are +sent, as well as a message template you can modify if you want. The +man page has all the details; I'll just mention two more here. + ++$$--edit-cover$$+ will open an editor and let you write an +introductory message; all the patch mails will then be sent as replies +to this 'cover message'. This is usually a good idea if you send more +than one patch, so that reviewers can get a quick overview of the +patches you sent. + ++$$--edit-patches$$+ will let you edit each patch before it is sent. +You can change anything, but note that you are only editing the +outgoing mail, not the patch itself; if you want to make changes to +the patch, you probably want to use the regular StGit commands to do +so. What this 'is' useful for, though, is to add notes for the patch +recipients: + +---------------------------------------------------------------------- +From: Audrey U. Thor +Subject: [PATCH] First line of the commit message + +The rest of the commit message + +--- + +Everything after the line with the three dashes and before the diff is +just a comment, and not part of the commit message. If there's +anything you want the patch recipients to see, but that shouldn't be +recorded in the history if the patch is accepted, write it here. + + stgit/main.py | 1 + + 1 files changed, 1 insertions(+), 0 deletions(-) + + +diff --git a/stgit/main.py b/stgit/main.py +index e324179..6398958 100644 +--- a/stgit/main.py ++++ b/stgit/main.py +@@ -171,6 +171,7 @@ def _main(): + sys.exit(ret or utils.STGIT_SUCCESS) + + def main(): ++ print 'My first patch!' + try: + _main() + finally: +---------------------------------------------------------------------- + + +Rebasing a patch series +----------------------- + +While you are busy writing, submitting, and revising your patch +series, other people will be doing the same thing. As a result, even +though you started writing your patches on top of what was the latest +history at the time, your stack base will grow ever more out of date. + +When you clone a repository, - stg init + $ stg clone http://homepage.ntlworld.com/cmarinas/stgit.git stgit -Run the 'stg init' command for any pre-existing GIT branches intended to -be used with StGIT. -You can switch between GIT branches with: +you initially get one local branch, +master+. You also get a number of +'remote' branches, one for each branch in the repository you cloned. +In the case of the StGit repository, these are ++remotes/origin/stable+, +remotes/origin/master+, and ++remotes/origin/proposed+. +remotes+ means that it's not a local +branch, just a snapshot of a branch in another repository; and ++origin+ is the default name for the first remote repository (you can +set up more; see the man page for +git remote+). - stg branch [] +Right after cloning, +master+ and +remotes/origin/master+ point at the +same commit. When you start writing patches, +master+ will advance, +and always point at the current topmost patch, but ++remotes/origin/master+ will stay the same because it represents the +master branch in the repository you cloned from -- your 'upstream' +repository. -This checks out the named branch and places you at the topmost applied -StGIT patch in that branch. -Alternately, you can create branches using only StGIT commands, which -will automatically prepare them for use with StGIT: +Unless you are the only one working on the project, however, the +upstream repository will not stay the same forever. New commits will +be added to its branches; to update your clone, run - stg branch --create + $ git remote update +This will update all your remote branches, but won't touch your local +branches. To get the latest changes into your local +master+ branch, +use linkstg:rebase[]: -Working with remote repositories --------------------------------- + $ stg rebase remotes/origin/master -With a single command, StGIT can create and initialize a GIT repository -which mirrors a remote GIT repository. This is known as cloning. All GIT -transports are supported. -To clone a repository, use: +This command will do three things: - stg clone + 1. Pop all patches, so that your local branch (+master+, in this + example) points at the stack base. This is the same commit that + +remotes/origin/master+ pointed at at the time you started + writing your patches. -This creates a fresh local repository, initialises a GIT database in it, -pulls the latest version of the remote, and creates and initialises a -'master' branch for use with StGIT. -At any time you can pull the latest changes from the remote repository. -By default, StGIT pulls from the location stored in .git/branches/ -origin, and updates the base of the current branch. -To pull the latest changes from a remote repository, use: + 2. Set the stack base to the given commit (the current, updated + value of +remotes/origin/master+). - stg pull [ or 'origin'] + 3. Push the patches that were popped in the first step. -This command removes all applied StGIT patches from the current branch, -updates the branch's base commit, then attempts to re-apply the patches. -Any merge conflicts will halt this process, allowing you to clean up the -conflicts and continue (see below). -If the maintainer of the remote repository includes one of your patches -in the published repository that you pull from, StGIT can usually -recognize that an incoming patch from the remote matches one of yours, -and it turns your local version into an empty patch. -To automatically delete empty patches after a pull, use: +The end result is that your patches are now applied on top of the +latest version of +remotes/origin/master+. - stg clean +The primary reason for rebasing is to reduce the amount of conflicts +between your work and others'. If one of your patches changes the same +part of the same file as a patch someone else has written, you will +get a conflict when you run linkstg:rebase[] the next time after the +other person's patch has been accepted upstream. It is almost always +less work to rebase often and resolve these one at a time, rather than +a whole lot at once. After all, you have to rebase eventually; if you +mail out patches that are based on an outdated branch, everyone who +tries to apply them has to resolve the conflicts instead. There are +more effective ways to get popular. -As a convention, you should avoid working in the 'master' branch and use -it only as a reference, since it reflects someone else's work. If you -decide to publish your GIT repository, you'll want your own work -separated into its own branch to make it convenient for others to pull -just your patches. -Getting started: creating a patch ---------------------------------- +When your patches are accepted +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Changes to your working directory are saved in a patch. An StGIT patch -is simply a saved set of modifications to your working directory, plus a -saved description. To create an empty StGIT patch in the current branch: +If and when some or all of your patches are accepted upstream, you +update and rebase just like usual -- but be sure to use the ++$$--merged$$+ flag to linkstg:rebase[]: - stg new + $ git remote update + $ stg rebase --merged remotes/origin/master -To save the changes you've made (that is, to refresh a patch), use: +This flag makes the rebase operation better at detecting that your +patches have been merged, at some cost in performance. - stg refresh +The patches that had been merged will still be present in your patch +stack after the rebase, but they will be empty, since the change they +added is now already present in the stack base. Run linkstg:clean[] to +get rid of such empty patches if you don't want them hanging around: -To discard changes in your working directory, use: + $ stg clean - git checkout -f -This restores your working directory to the state it was in the last -time the patch was refreshed. -Modified files that haven't been saved via a refresh operation can be -viewed with: +Importing patches +----------------- - stg status +While you are busy producing patches, there's hopefully someone -- the +'maintainer' -- at the other end who recieves them and 'applies' them +to her Git tree, which is then published for all (or parts of) the +world to see. -You can view modified files that have already been saved into a patch: +It's perfectly fine for this person to not have the foggiest idea what +StGit is. In that case, she'll probably apply your patches with +something like +git am+, and everything will just work, exactly as if +you'd used Git to send those patches. But she might be an StGit user +too, in which case she might use linkstg:import[]. - stg files +There are basically four kinds if stuff you can import with +linkstg:import[]: -The 'stg refresh' command automatically notes changes to files that -already exist in the working directory (it also notices if you remove -them), but you have to tell StGIT explicitly if you add or rename a -file: + 1. A patch in a file. - git add new-file + 2. Several files containing one patch each, and a 'series' file + listing those other files in the correct order. -to add a file, and + 3. An e-mail containing a single patch. - mv old-file new-file - git add new-file + 4. A mailbox file (in standard Unix +mbox+ format) containing + multiple e-mails with one patch in each. -or simply - git mv old-file new-file +Importing a plain patch +~~~~~~~~~~~~~~~~~~~~~~~ -to move a file. +Importing a plain patch, such as produced by e.g. GNU +diff+, +git +diff+, +git show+, linkstg:diff[], or linkstg:show[], is very easy. +Just say + $ stg import my-patch -Stack manipulation: managing multiple patches ---------------------------------------------- +and you'll have a new patch at the top of your stack. -StGIT can manage more than one patch at a time. A series of StGIT -patches in a GIT branch are known collectively as a stack. The new patch -you created above is now the topmost patch in your stack. You can always -see the name of the topmost (current) patch with: +If you don't give a file name on the command line, linkstg:import[] +will read the patch from its standard input -- in other words, you can +pipe a patch to it directly from the command that produces it. - stg top +By default, the new patch's name will be taken from the file name, and +its commit message and author info will be taken from the beginning of +the patch, if they are there. However, there are command line switches +to override all of these things; see the man page for details. -The topmost patch is used as the default patch for most StGIT -operations. It is the default target of the 'stg refresh' command, for -example. -Patches that are pushed onto the stack are referred to as applied, and -patches that are popped off the stack are referred to as unapplied. -To push/pop a patch to/from a stack: - stg push [--all | ] - stg pop [--all] +Importing several patches at once +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -The last patch you pushed is the topmost patch. This patch is always in -the applied list; StGIT can't operate on an unapplied patch unless you -apply it first. -You can display the order of patches in a stack with one of these -commands: +Some programs -- among them linkstg:export[] -- will create a bunch of +files with one patch in each, and a 'series' file (often called ++series+) listing the other files in the correct order. Give ++$$--series$$+ and the name of the series file to linkstg:import[], +and it will import all the patches for you, in the correct order. - stg series - stg applied - stg unapplied -By default the 'stg push' command applies the first patch in the -unapplied list, but you can push any patch in the unapplied list by -giving the name of the patch. This is useful if you want to reorder the -patches in a stack. -During a push operation, merge conflicts can occur (especially if you -are changing the order of the patches in your stack). If the push causes -merge conflicts, they need to be fixed and 'stg resolved' run (see -below). A 'push' operation can also be reverted with 'stg push --undo'. -A few more stack basics; to rename a patch: +Importing a patch from an e-mail +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - stg rename +Importing a patch from an e-mail is simple too: -To delete a patch: + $ stg import --mail my-mail - stg delete +The e-mail should be in standard Git mail format (which is what e.g. +linkstg:mail[] produces) -- that is, with the patch in-line in the +mail, not attached. The authorship info is taken from the mail +headers, and the commit message is read from the 'Subject:' line and +the mail body. -This permanently discards the named patch. In other words, the patch no -longer appears in either the applied or unapplied lists, and cannot be -reapplied to the series. -You may want to make patches in your stack a permanent part of your GIT -repository, for example if you are publishing your repository to others. -To do this, use: +If you don't give a file name, the mail will be read from the standard +input. This means that, if your mail reader supports it, you can pipe +a mail directly to +stg import $$--mail$$+ and the patch will be +applied. - stg commit -This merges all applied patches in your patch series into the GIT -repository and removes them from your stack. Use this command only if -you want to permanently store the applied patches and no longer manage -them with StGIT. +Importing a mailbox full of patches +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Converting between StGIT patches and text diffs ------------------------------------------------ +Finally, in case importing one patch at a time is too much work, +linkstg:import[] also accepts an entire Unix +mbox+-format mailbox, +either on the command line or on its standard input; just use the ++$$--mbox$$+ flag. Each mail should contain one patch, and is imported +just like with +$$--mail$$+. + +Mailboxes full of patches are produced by e.g. linkstg:mail[] with the ++$$--mbox$$+ flag, but most mail readers can produce them too, meaning +that you can copy all the patch mails you want to apply to a separate +mailbox, and then import them all in one go. + + +Other stuff that needs to be placed somewhere +============================================= + + +Undo +---- + +TODO:: undo, redo, log, reset + + +Interoperating with Git +----------------------- + +TODO:: + +* git commit + repair + +* git reset HEAD~n + repair + +* don't do git rebase or git merge, because it won't work + + +Patch stuff +----------- + +TODO:: This section needs revising. I've only fixed the formatting. +Most of it should go under "Workflow: Tracking branch" + +As mentioned in the introduction, StGit stores modifications to your +working tree in the form of Git commits. This means if you want to +apply your changes to a tree not managed by Git, or send your changes +to someone else in e-mail, you need to convert your StGit patches into +normal textual diffs that can be applied with the GNU patch command. +linkstg:diff[] is a powerful way to generate and view textual diffs of +patches managed by StGit. -As mentioned in the introduction, StGIT stores modifications to your -working tree in the form of GIT commits. This means if you want to apply -your changes to a tree not managed by GIT, or send your changes to -someone else in e-mail, you need to convert your StGIT patches into -normal textual diffs that can be applied with the GNU 'patch' command. -The 'stg diff' command is a powerful way to generate and view textual -diffs of patches managed by StGIT. To view a diff of the topmost patch: - stg diff -r / + $ stg diff -r / Observe that this does not show any changes in the working directory -that have not been saved by a 'refresh'. To view just the changes you've -made since the last refresh, use: +that have not been saved by a linkstgsub:refresh[]. To view just the +changes you've made since the last refresh, use: - stg diff -r /top + $ stg diff -r /top If you want to see the changes made by the patch combined with any unsaved changes in the working directory, try: - stg diff -r /bottom + $ stg diff -r /bottom You can also show the changes to any patch in your stack with: - stg diff -r / + $ stg diff -r / Use this command to view all the changes in your stack up through the current patch: - stg diff -r base + $ stg diff -r base -The 'stg diff' command supports a number of other features that are very -useful. Be sure to take a look at the help information for this command. -To convert your StGIT patches into patch files: +linkstg:diff[] supports a number of other features that are very +useful. Be sure to take a look at the help information for this +command. To convert your StGit patches into patch files: - stg export [--range=[[:]]] [] + $ stg export [--range=[[:]]] [] -The 'export' command supports options to automatically number the -patches (-n) or add the '.diff' extension (-d). If you don't tell "stg -export" where to put the patches, it will create directory named "patch- -branchname" in your current directory, and store the patches there. -To e-mail a patch or range of patches: +linkstg:export[] supports options to automatically number the patches +(+-n+) or add the +.diff+ extension (+-d+). If you don't tell +linkstgsub:export[] where to put the patches, it will create directory +named +patch-+ in your current directory, and store the +patches there. To e-mail a patch or range of patches: - stg mail [--to=...] (--all | --range=[[:]] | ) + $ stg mail [--to=...] (--all | --range=[[:]] | ) -"stg mail" has a lot of options, so read the output of "stg mail -h" for -more information. -You can also import an existing GNU diff patch file as a new StGIT patch -with a single command. "stg import" will automatically parse through the -patch file and extract a patch description. Use: +linkstg:mail[] has a lot of options, so read the output of +stg mail +-h+ for more information. - stg import [] +You can also import an existing GNU diff patch file as a new StGit +patch with a single command. linkstg:import[] will automatically parse +through the patch file and extract a patch description. Use: -This is the equivalent of "stg new" followed by "patch -i ", then -"stg refresh -e". -Sometimes the patch file won't apply cleanly. In that case, "stg import" -will leave you with an empty StGIT patch, to which you then apply the -patch file by hand using "patch -i" and your favorite editor. -To merge a GNU diff file (defaulting to the standard input) into the -topmost patch: + $ stg import [] - stg fold [] +This is the equivalent of -This command supports a '--threeway' option which applies the patch onto -the bottom of the topmost one and performs a three-way merge. + $ stg new + $ patch -i + $ stg refresh -e +Sometimes the patch file won't apply cleanly. In that case, +linkstg:import[] will leave you with an empty StGit patch, to which +you then apply the patch file by hand using "patch -i" and your +favorite editor. -Advanced Usage -============== +To merge a GNU diff file (defaulting to the standard input) into the +topmost patch: -Handling merge conflicts ------------------------- + $ stg fold [] -Pushing a patch on the stack can fail if the patch cannot be applied -cleanly. This usually happens if there are overlapping changes in the -tree, the patch depends on another patch which is not applied, or if a -patch was not merged upstream in the exact form it was sent. -The 'push' operation stops after the first patch with conflicts. The -'status' command shows the conflict files by marking them with a 'C'. If -the 'keeporig' options is set to 'yes' (the default), the original files -involved in the merge operations are left in the tree as .older, -.local and .remote for better analysis of the conflict. If -'diff3' is used as the merger (the default), markers are added to the -conflicted files as well. -Run the 'resolved' command to mark the conflicts resolved and remove the -temporary merge files from the working tree. Then run the 'refresh' -command to update the StGIT patch with the modifications you made to -resolve the conflict. - - -Configuration file ------------------- - -StGIT tries to read the configuration options from the following files: -/etc/stgitrc, ~/.stgitrc and .git/stgitrc. The latter overrides the -options in the former files. If no file is found, the defaults are used. -An example configuration file with options description can be found in -the examples/ directory. Most users would probably only define the -'smtpserver' option used by the 'mail' command. -The gitmergeonefile.py script does the three-way merging on individual -files using the tool specified by the 'merger' option. The user can -specify a smarter tool to be used. +This command supports a +$$--threeway$$+ option which applies the +patch onto the bottom of the topmost one and performs a three-way +merge. Templates --------- -The 'export' and 'mail' commands use templates for generating the patch -files or e-mails. The default templates are installed under / -share/stgit/templates/ and, combined with the extra options available -for the commands, should be enough for most users. The template format -uses the standard Python string formatting rules. The variables -available are shown in the the help message for the commands. -The 'mail' command can also send an initial e-mail for which there is no -default template. The /share/stgit/examples/firstmail.tmpl file -can be used as an example. -A default description for new patches can be defined in the .git/ -patchdescr.tmpl file. This is useful for things like signed-off-by -lines. - - -Merging two patches into one ----------------------------- - -There is no command to do this directly at the moment but one can export -the patch to be merged and use the 'stg fold' command on the generated -diff file. Assuming that the merged patch was not already applied, the -operation will succeed. Pushing the merged patch onto the stack will -result in an empty patch (StGIT notifying the user) that can be safely -deleted. - - -Technical Information -===================== - -A bit of StGIT patch theory ---------------------------- - -We assume that a patch is a diff between two nodes - bottom and top. A -node is a commit SHA1 id or tree SHA1 id in the GIT terminology: - - P - patch - N - node - - P = diff(Nt, Nb) - - Nb - bottom (start) node - Nt - top (end) node - Nf - first node (for log generation) - -For an ordered stack of patches: - - P1 = diff(N1, N0) - P2 = diff(N2, N1) - ... - - - Ps = P1 + P2 + P3 + ... = diff(Nst, Nsb) - - Ps - the big patch of the whole stack - Nsb - bottom stack node (= N0) - Nst - top stack node (= Nn) - -Applying (pushing) a patch on the stack (Nst can differ from Nb) is done -by diff3 merging. The new patch becomes: - - P' = diff(Nt', Nb') - Nb' = Nst - Nt' = diff3(Nst, Nb, Nt) - -(note that the diff3 parameters order is: branch1, ancestor, branch2) -The above operation allows easy patch re-ordering. -Removing (popping) a patch from the stack is done by simply setting the -Nst to Nb. - - -Layout of the .git directory ----------------------------- - - HEAD -> refs/heads/ - objects/ - ??/ - ... - refs/ - heads/ - master - the master commit id - ... - tags/ - ... - branches/ - ... - patches/ - master/ - applied - list of applied patches - unapplied - list of not-yet applied patches - current - name of the topmost patch - patch1/ - bottom - the bottom id of the patch - top - the top id of the patch - description - the patch description - authname - author's name - authemail - author's e-mail - commname - committer's name - commemail - committer's e-mail - patch2/ - ... - ... - ... +TODO:: This section needs revising. I've only fixed the formatting. + +linkstg:export[] and linkstg:mail[] use templates for generating the +patch files or e-mails. The default templates are installed under ++/share/stgit/templates/+ and, combined with the extra options +available for these commands, should be enough for most users. The +template format uses the standard Python string formatting rules. The +variables available are listed in the the manual pages for each +command. linkstg:mail[] can also send an initial 'cover' e-mail for +which there is no default template. The ++/share/stgit/examples/firstmail.tmpl+ file can be used as an +example. A default description for new patches can be defined in the ++.git/ patchdescr.tmpl+ file. This is useful for things like +signed-off-by lines.