简体   繁体   中英

mercurial hg partial checkin

It is a very simple and stupid question,

I am working on 2 tasks and modified 2 sets of files in the code.

Now when I type 'hg ci', it checks in all the files. Can I remove certain files from the checkin ie do checking for only one task?

If I remove the files in the 'check in message' will they be removed from the checkin

Thanks for all the answers

This seems like a big flaw, My use case is very simple and general. Most of the time dev are working on various tasks , some are ready , some are not, bug fixes etc.

Now the only simple solution seems to be multiple local repos or clones

使用hg ci <files>...仅提交工作目录中的某些文件。

If you want to pick file by file you can use the record command . It ships with mercurial, but you have to turn it on if you want to use it by putting: record= in the [extensions] section of your ~/.hgrc .

It goes hunk by hunk, but you can answer for a whole file:

y - record this change
n - skip this change

s - skip remaining changes to this file
f - record remaining changes to this file

d - done, skip remaining changes and files
a - record all changes to all remaining files
q - quit, recording no changes

? - display help

I'll point out that if you're committing some files but not others it's certain that you've not run your test suite on the one change without the other, but maybe that doesn't apply in your case.

The real problem here is the fact that you're doing changes related to different tasks jumbled together. Mercurial has a few ways you can keep things separate.

Task Branches

Suppose you've been working on a task and you've checked in a few times since you last pulled, but things aren't ready to share yet.

o----o----B----o----o----o

Here, B is the revision where you started your changes. What we do is (after making sure our current changes are checked in):

> hg update -r B
<do our work on the other task>
> hg commit

We've now created a new branch with the changes for this task separated from the changes for our original task.

o----o----B----o----o----o
           \
            ----o

We can do this for as many different tasks as we want. The only problem is that sometimes remembering which branch is which can be awkward. This is where features like bookmarks come in useful. A bookmark is a tag which moves forward as commits are made so that it always points at the head of a branch.

Mercurial Queues

MQ adds the ability to work on changes incrementally and move between them by push ing and pop ing then off a stack (or "Queue" I guess). So if I had a set of uncommitted changes that I needed to split up I'd:

> hg qrecord taska
> hg qrecord taskb
> hg qrecord taskc

I'd use the record extension (or more likely the crecord extension) to select which parts of files I want to select.

If I needed to go back to taska and make some changes:

> hg qpop; hg qpop    # pop two off the queue to go back to task a
<Do changes>
> hg qrefresh         # update task a with the new changes

When I want to turn the queue into normal changesets:

> hg qpush or hg qpop # get the changes I want converted onto the queue
> hg qfinish -a       # converts mq changes to normal changesets

There's other methods too, but that will do for now.

This isn't possible with mercurial out of the box. As have been suggested there are several ways of selecting what files you want to commit. To get this function via the commit message template, you would need an extension or a shell script wrapping the commit command. Here's one way to do that:

[alias]
ci = ! hg-partial-commit

hg-partial-commit:

#!/bin/sh
# partial commit

edit=$(mktemp ${TMPDIR:-/tmp}/$(basename $0).XXXXXXXXXXXX)
filelist=$(mktemp ${TMPDIR:-/tmp}/$(basename $0).XXXXXXXXXXXX)
logmessage=$(mktemp ${TMPDIR:-/tmp}/$(basename $0).XXXXXXXXXXXX)
cleanup="rm -f '$edit' '$filelist' '$logmessage'"
trap "$cleanup" 0 1 2 3 15

(
    echo user: $(hg debugconfig ui.username)
    echo branch: $(hg branch)
    hg parents --template 'parent: {rev}:{node|short}  {author}  {date|isodate}\n'
    echo
    echo 'Enter commit message.  Select files to commit by deleting lines:'
    hg status 'set:not unknown()' | sed -e 's/^/@/'
) | sed -e 's/^/HG: /' >"$edit"

${VISUAL:-${EDITOR:-vi}} "$edit"
egrep -v '^HG:' "$edit" >"$logmessage"
egrep '^HG: @' "$edit" | cut -c8- >"$filelist"

hg commit -l "$logmessage" "listfile:$filelist"
$cleanup

You will unavoidably have to either specify the files that you want to add or the files you want to leave out. If you have a lot of files, as you indicate above, the following steps will simplify the procedure (I'm assuming a UNIX-ish system here, Windows would be slightly different).

First, generate a list of changed files:

hg status -mard -n >/tmp/changedlist.txt

The -mard options will list all files that were modified, added, removed, or delated. The -n option will list them without the status prefix so that all you have is a raw list of files.

Second, edit /tmp/changedlist.txt with your favorite text editor so that it contains only the files you wish to commit.

Third, commit these files:

hg commit `cat /tmp/changedlist.txt`

You will be able to review the files to be committed before actually performing the commit.

Alternatively, you can add more files to a commit incrementally by using

`hg commit --amend file...`

Here, hg commit --amend will not create a new commit, but add the new files to the existing commit. So, you start out with committing just a couple of files, then incrementally adding more until you are done. This still requires you to type all of them in.

For yet another alternative, you can use Mercurial Queues to split a commit in more sophisticated ways, but that's a bit more of an advanced topic.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM