57

I just started using Git alongside Mercurial to familiarize myself with Git.

I use the mq extension in Mercurial extensively to manage local patches, and I'm looking for a Git equivalent.

Should I just use Git branch? Or are there better ways to manage local patches that enable easily applying and removing the patches?

Thanks,

Martin Geisler
  • 72,968
  • 25
  • 171
  • 229
John Weldon
  • 39,849
  • 11
  • 94
  • 127

4 Answers4

32

Check out "Patch-management Interface layers" section of Interfaces, Frontends And Tools page on Git Wiki. There are listed two patch management interfaces, roughly equivalent to Mercurials 'mq' extension:

  • StGIT (Stacked Git), older of the two, written in Python, uses two snapshots to represent patch
  • Guilt (formerly 'gq'), written as series of bash scripts, series file and the patches (one per file) are stored as plain text file.
  • pg (Patchy Git) is deprecated, and no longer maintained.

But if you don't need more advanced usage, you can use instead "git rebase --interactive" to reorder, squash and split patches. And to manage your branch against current version of upstream, "git rebase" usually would suffice.

sourcejedi
  • 3,051
  • 2
  • 24
  • 42
Jakub Narębski
  • 309,089
  • 65
  • 217
  • 230
  • 1
    Can you name one of those "advanced usages"? I think `git rebase --interactive` pretty much eliminates the need for something like Mq. – kizzx2 Aug 18 '10 at 15:32
  • 7
    **@kizzx2:** `git rebase --interactive` forces you to deal with the whole series in sequence. With patch management interfaces you can easily go back and forth between patches to edit them. You can also view history of a changes to patch, add new commit in the middle of series, cherry-pick other commit, etc. – Jakub Narębski Aug 19 '10 at 10:13
  • 1
    @jakub, doesn't `git checkout` will allow you to go back and forth between commits? What's so easy about managing patches. The whole point of git, is that walking throughout commits is easy. – Elazar Leibovich Nov 09 '10 at 18:07
  • 5
    @Elazar: if you checkout earlier commit, e.g. HEAD~2, first you would land on *detached HEAD* (unnamed branch); second, after changing the commit e.g. via amending it, the formerly following commits (HEAD~1, HEAD~0) **would not be on top of it** (that's because in git reference to comit used e.g. for 'parent' link is based in SHA-1 of its contents - if commit changes, its SHA-1 changes too). – Jakub Narębski Nov 09 '10 at 22:30
  • @jakub, of course the other commits won't be on top of it. This is because they might break if they would be on top of it (just like in `MQ` the patches on top might be rejected). So what you should do after amending the commit is to rebase all those other commits so that after rebase they would be on top of it. Moving the HEAD to the current commit is not a problem, really, it's a matter of `git reset`, but you don't need that, just write down the first five letters of the relevant commit's hash. – Elazar Leibovich Nov 10 '10 at 04:24
  • @Elazar: You would need to rebase commits that come after the commit you changed with 'git checkout HEAD~2' + 'git commit --amend'... so why not use `git rebase --interactive` from the start? I wrote it as an alternative solution in my answer. – Jakub Narębski Nov 10 '10 at 18:30
  • @Jakub, my point was that doing all those things you mentioned (going back and forth through patches) is easy with the rebase approach as well. No gain for using MQ for this aspect. – Elazar Leibovich Nov 10 '10 at 20:29
  • 2
    @Elazar: with patch management interface (e.g. StGit for git, or mq for Mercurial), it is easy to go to 4th patch, then 2nd patch, then apply all, then go to 3rd and add new patch. Interactive rebase means got to 4th patch, then apply all, go to 2nd patch, then apply all... or use checkout + rebase + reset, which is IMHO slightly harder to use. – Jakub Narębski Nov 10 '10 at 21:27
  • @Jakub, got you. What we should do is, make `hg mq` automatically rebase when applying a patch, if we know on which revision should this patch be applied. – Elazar Leibovich Nov 11 '10 at 09:03
32

Disclaimer: I'm not an hg user, so I have read about hg but don't have much first hand experience of using it.

git provides several very powerful and flexible tools for managing branches in a 'patch queue' style so for many basic (and even some quite complex) use cases, native git is sufficiently powerful.

Typically, most projects keep a central stable master branch which only gains new commits and is never 'rewound' so commits in the master branch are fixed.

On top of this a maintainer (or a developer) may maintain one or more fluid branches of work-in-progress patches (i.e. commits) which are based on the stable branch.

Typical patch managing activities include:

rebasing the patch queue onto the lastest stable branch - use git rebase,

duplicating the patch queue onto an old maintentance branch - use git branch and git rebase,

reordering patches in the queue - use git rebase --interactive (aka git rebase -i) using a text editor to reorder the queue.

squashing patches - use git rebase -i with the squash directive

altering patches or patch commit messages - use git rebase -i (spot a theme?) with the edit directive.

Any activity that alters a patch in any way (i.e. its contents, description or parentage) will create a new commit with a new commit id for that patch. The fact that the old commits may be thrown away and replaced regularly before they are promoted to the stable master branch is the only thing that makes them a 'patch queue' rather than a branch, but this is a project convention rather than any physical difference in the data that makes up the commits. To git they are identical objects.

To promote a patch to a 'real' commit is just moving the patch to the front of the queue and merging it into the master branch. After moving the patch to the front of the queue, it is just the same as a normal commit based on the master branch, so merging it just fast-forwards the master branch pointer to point at the patch commit.

Publishing this commit as a 'stable' master patch is the act that says: this is now a commit that will not change and is part of the immutable history of the project.

CB Bailey
  • 755,051
  • 104
  • 632
  • 656
  • 1
    I generally use Mercurial, but this is probably the best description of the rational behind git branches I've seen. Thanks! :) – rpjohnst Apr 26 '11 at 20:19
  • 2
    One feature of Mercurial Queues that I use extensively in one project is to "export" them by just copying the .hg/patches directory. Being able to store and manage the patches externally from the repo is crucial. Admittedly this usage is highly unusual, but does git have anything that provides similar functionality? – Paul Moore Feb 01 '14 at 14:49
  • 1
    @PaulMoore Just do a `git format-patch` on the patches you want exported, possibly even saving them to an mbox file if you want, so you can do a `git am` on it to apply all of them at once simply. – remmy Jul 09 '14 at 13:06
  • @kyrias Thanks. I'd not seen `format-patch` and `am` before. I shall have a read about them. – Paul Moore Jul 10 '14 at 13:59
9

Just use a branch and rebase it against your upstream branch regularly. This is both easier to manage and safer than using mq (to which I've lost data in the past).

Dustin
  • 89,080
  • 21
  • 111
  • 133
7

Git doesn't really provide this feature itself. Depending on your uses, you might be able to get by with "git stash" and/or branches, but it'll be pretty basic. If people have more advanced patch management needs with git, they seem to turn to Quilt or StGit: see http://git.or.cz/gitwiki/PatchManagement

C Pirate
  • 444
  • 3
  • 7