Skip to content

Commit 46e91b6

Browse files
pcloudsgitster
authored andcommitted
checkout: split part of it to new command 'restore'
Previously the switching branch business of 'git checkout' becomes a new command 'switch'. This adds the restore command for the checking out paths path. Similar to git-switch, a new man page is added to describe what the command will become. The implementation will be updated shortly to match the man page. A couple main differences from 'git checkout <paths>': - 'restore' by default will only update worktree. This matters more when --source is specified ('checkout <tree> <paths>' updates both worktree and index). - 'restore --staged' can be used to restore the index. This command overlaps with 'git reset <paths>'. - both worktree and index could also be restored at the same time (from a tree) when both --staged and --worktree are specified. This overlaps with 'git checkout <tree> <paths>' - default source for restoring worktree and index is the index and HEAD respectively. A different (tree) source could be specified as with --source (*). - when both index and worktree are restored, --source must be specified since the default source for these two individual targets are different (**) - --no-overlay is enabled by default, if an entry is missing in the source, restoring means deleting the entry (*) I originally went with --from instead of --source. I still think --from is a better name. The short option -f however is already taken by force. And I do think short option is good to have, e.g. to write -s@ or -s@^ instead of --source=HEAD. (**) If you sit down and think about it, moving worktree's source from the index to HEAD makes sense, but nobody is really thinking it through when they type the commands. Signed-off-by: Nguyễn Thái Ngọc Duy <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 328c6cb commit 46e91b6

File tree

13 files changed

+257
-5
lines changed

13 files changed

+257
-5
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@
143143
/git-request-pull
144144
/git-rerere
145145
/git-reset
146+
/git-restore
146147
/git-rev-list
147148
/git-rev-parse
148149
/git-revert

Documentation/config/interactive.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@ interactive.singleKey::
22
In interactive commands, allow the user to provide one-letter
33
input with a single key (i.e., without hitting enter).
44
Currently this is used by the `--patch` mode of
5-
linkgit:git-add[1], linkgit:git-checkout[1], linkgit:git-commit[1],
5+
linkgit:git-add[1], linkgit:git-checkout[1],
6+
linkgit:git-restore[1], linkgit:git-commit[1],
67
linkgit:git-reset[1], and linkgit:git-stash[1]. Note that this
78
setting is silently ignored if portable keystroke input
89
is not available; requires the Perl module Term::ReadKey.

Documentation/git-checkout.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -570,7 +570,8 @@ $ git add frotz
570570

571571
SEE ALSO
572572
--------
573-
linkgit:git-switch[1]
573+
linkgit:git-switch[1],
574+
linkgit:git-restore[1]
574575

575576
GIT
576577
---

Documentation/git-reset.txt

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ The `<tree-ish>`/`<commit>` defaults to `HEAD` in all forms.
2525
the current branch.)
2626
+
2727
This means that `git reset <paths>` is the opposite of `git add
28-
<paths>`.
28+
<paths>`. This command is equivalent to
29+
`git restore [--source=<tree-ish>] --staged <paths>...`.
2930
+
3031
After running `git reset <paths>` to update the index entry, you can
3132
use linkgit:git-checkout[1] to check the contents out of the index to
@@ -86,8 +87,8 @@ but carries forward unmerged index entries.
8687
changes, reset is aborted.
8788
--
8889

89-
If you want to undo a commit other than the latest on a branch,
90-
linkgit:git-revert[1] is your friend.
90+
See "Reset, restore and revert" in linkgit:git[1] for the differences
91+
between the three commands.
9192

9293

9394
OPTIONS

Documentation/git-restore.txt

Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
git-restore(1)
2+
==============
3+
4+
NAME
5+
----
6+
git-restore - Restore working tree files
7+
8+
SYNOPSIS
9+
--------
10+
[verse]
11+
'git restore' [<options>] [--source=<tree>] [--staged] [--worktree] <pathspec>...
12+
'git restore' (-p|--patch) [<options>] [--source=<tree>] [--staged] [--worktree] [<pathspec>...]
13+
14+
DESCRIPTION
15+
-----------
16+
Restore specified paths in the working tree with some contents from a
17+
restore source. If a path is tracked but does not exist in the restore
18+
source, it will be removed to match the source.
19+
20+
The command can also be used to restore the content in the index with
21+
`--staged`, or restore both the working tree and the index with
22+
`--staged --worktree`.
23+
24+
By default, the restore sources for working tree and the index are the
25+
index and `HEAD` respectively. `--source` could be used to specify a
26+
commit as the restore source.
27+
28+
See "Reset, restore and revert" in linkgit:git[1] for the differences
29+
between the three commands.
30+
31+
OPTIONS
32+
-------
33+
-s <tree>::
34+
--source=<tree>::
35+
Restore the working tree files with the content from the given
36+
tree. It is common to specify the source tree by naming a
37+
commit, branch or tag associated with it.
38+
+
39+
If not specified, the default restore source for the working tree is
40+
the index, and the default restore source for the index index is
41+
`HEAD`. When both `--staged` and `--worktree` are specified,
42+
`--source` must also be specified.
43+
44+
-p::
45+
--patch::
46+
Interactively select hunks in the difference between the
47+
restore source and the restore location. See the ``Interactive
48+
Mode'' section of linkgit:git-add[1] to learn how to operate
49+
the `--patch` mode.
50+
+
51+
Note that `--patch` can accept no pathspec and will prompt to restore
52+
all modified paths.
53+
54+
-W::
55+
--worktree::
56+
-S::
57+
--staged::
58+
Specify the restore location. If neither option is specified,
59+
by default the working tree is restored. Specifying `--staged`
60+
will only restore the index. Specifying both restores both.
61+
62+
-q::
63+
--quiet::
64+
Quiet, suppress feedback messages. Implies `--no-progress`.
65+
66+
--progress::
67+
--no-progress::
68+
Progress status is reported on the standard error stream
69+
by default when it is attached to a terminal, unless `--quiet`
70+
is specified. This flag enables progress reporting even if not
71+
attached to a terminal, regardless of `--quiet`.
72+
73+
--ours::
74+
--theirs::
75+
When restoring files in the working tree from the index, use
76+
stage #2 ('ours') or #3 ('theirs') for unmerged paths.
77+
+
78+
Note that during `git rebase` and `git pull --rebase`, 'ours' and
79+
'theirs' may appear swapped. See the explanation of the same options
80+
in linkgit:git-checkout[1] for details.
81+
82+
-m::
83+
--merge::
84+
When restoring files on the working tree from the index,
85+
recreate the conflicted merge in the unmerged paths.
86+
87+
--conflict=<style>::
88+
The same as `--merge` option above, but changes the way the
89+
conflicting hunks are presented, overriding the
90+
`merge.conflictStyle` configuration variable. Possible values
91+
are "merge" (default) and "diff3" (in addition to what is
92+
shown by "merge" style, shows the original contents).
93+
94+
--ignore-unmerged::
95+
When restoring files on the working tree from the index, do
96+
not abort the operation if there are unmerged entries and
97+
neither `--ours`, `--theirs`, `--merge` or `--conflict` is
98+
specified. Unmerged paths on the working tree are left alone.
99+
100+
--ignore-skip-worktree-bits::
101+
In sparse checkout mode, by default is to only update entries
102+
matched by `<pathspec>` and sparse patterns in
103+
$GIT_DIR/info/sparse-checkout. This option ignores the sparse
104+
patterns and unconditionally restores any files in
105+
`<pathspec>`.
106+
107+
--overlay::
108+
--no-overlay::
109+
In overlay mode, the command never removes files when
110+
restoring. In no-overlay mode, tracked files that do not
111+
appear in the `--source` tree are removed, to make them match
112+
`<tree>` exactly. The default is no-overlay mode.
113+
114+
EXAMPLES
115+
--------
116+
117+
The following sequence switches to the `master` branch, reverts the
118+
`Makefile` to two revisions back, deletes hello.c by mistake, and gets
119+
it back from the index.
120+
121+
------------
122+
$ git switch master
123+
$ git restore --source master~2 Makefile <1>
124+
$ rm -f hello.c
125+
$ git restore hello.c <2>
126+
------------
127+
128+
<1> take a file out of another commit
129+
<2> restore hello.c from the index
130+
131+
If you want to restore _all_ C source files to match the version in
132+
the index, you can say
133+
134+
------------
135+
$ git restore '*.c'
136+
------------
137+
138+
Note the quotes around `*.c`. The file `hello.c` will also be
139+
restored, even though it is no longer in the working tree, because the
140+
file globbing is used to match entries in the index (not in the
141+
working tree by the shell).
142+
143+
To restore all files in the current directory
144+
145+
------------
146+
$ git restore .
147+
------------
148+
149+
or to restore all working tree files with 'top' pathspec magic (see
150+
linkgit:gitglossary[7])
151+
152+
------------
153+
$ git restore :/
154+
------------
155+
156+
To restore a file in the index to match the version in `HEAD` (this is
157+
the same as using linkgit:git-reset[1])
158+
159+
------------
160+
$ git restore --staged hello.c
161+
------------
162+
163+
or you can restore both the index and the working tree (this the same
164+
as using linkgit:git-checkout[1])
165+
166+
------------
167+
$ git restore --source=HEAD --staged --worktree hello.c
168+
------------
169+
170+
or the short form which is more practical but less readable:
171+
172+
------------
173+
$ git restore -s@ -SW hello.c
174+
------------
175+
176+
SEE ALSO
177+
--------
178+
linkgit:git-checkout[1],
179+
linkgit:git-reset[1]
180+
181+
GIT
182+
---
183+
Part of the linkgit:git[1] suite

Documentation/git-revert.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ should see linkgit:git-checkout[1], specifically the `git checkout
3030
<commit> -- <filename>` syntax. Take care with these alternatives as
3131
both will discard uncommitted changes in your working directory.
3232

33+
See "Reset, restore and revert" in linkgit:git[1] for the differences
34+
between the three commands.
35+
3336
OPTIONS
3437
-------
3538
<commit>...::

Documentation/git.txt

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,26 @@ people via patch over e-mail.
210210

211211
include::cmds-foreignscminterface.txt[]
212212

213+
Reset, restore and revert
214+
~~~~~~~~~~~~~~~~~~~~~~~~~
215+
There are three commands with similar names: `git reset`,
216+
`git restore` and `git revert`.
217+
218+
* linkgit:git-revert[1] is about making a new commit that reverts the
219+
changes made by other commits.
220+
221+
* linkgit:git-restore[1] is about restoring files in the working tree
222+
from either the index or another commit. This command does not
223+
update your branch. The command can also be used to restore files in
224+
the index from another commit.
225+
226+
* linkgit:git-reset[1] is about updating your branch, moving the tip
227+
in order to add or remove commits from the branch. This operation
228+
changes the commit history.
229+
+
230+
`git reset` can also be used to restore the index, overlapping with
231+
`git restore`.
232+
213233

214234
Low-level commands (plumbing)
215235
-----------------------------

Documentation/gitcli.txt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,18 @@ See also http://marc.info/?l=git&m=116563135620359 and
209209
http://marc.info/?l=git&m=119150393620273 for further
210210
information.
211211

212+
Some other commands that also work on files in the working tree and/or
213+
in the index can take `--staged` and/or `--worktree`.
214+
215+
* `--staged` is exactly like `--cached`, which is used to ask a
216+
command to only work on the index, not the working tree.
217+
218+
* `--worktree` is the opposite, to ask a command to work on the
219+
working tree only, not the index.
220+
221+
* The two options can be specified together to ask a command to work
222+
on both the index and the working tree.
223+
212224
GIT
213225
---
214226
Part of the linkgit:git[1] suite

Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -799,6 +799,7 @@ BUILT_INS += git-format-patch$X
799799
BUILT_INS += git-fsck-objects$X
800800
BUILT_INS += git-init$X
801801
BUILT_INS += git-merge-subtree$X
802+
BUILT_INS += git-restore$X
802803
BUILT_INS += git-show$X
803804
BUILT_INS += git-stage$X
804805
BUILT_INS += git-status$X

builtin.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,7 @@ extern int cmd_remote_fd(int argc, const char **argv, const char *prefix);
214214
extern int cmd_repack(int argc, const char **argv, const char *prefix);
215215
extern int cmd_rerere(int argc, const char **argv, const char *prefix);
216216
extern int cmd_reset(int argc, const char **argv, const char *prefix);
217+
extern int cmd_restore(int argc, const char **argv, const char *prefix);
217218
extern int cmd_rev_list(int argc, const char **argv, const char *prefix);
218219
extern int cmd_rev_parse(int argc, const char **argv, const char *prefix);
219220
extern int cmd_revert(int argc, const char **argv, const char *prefix);

builtin/checkout.c

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,11 @@ static const char * const switch_branch_usage[] = {
3838
NULL,
3939
};
4040

41+
static const char * const restore_usage[] = {
42+
N_("git restore [<options>] [<branch>] -- <file>..."),
43+
NULL,
44+
};
45+
4146
struct checkout_opts {
4247
int patch_mode;
4348
int quiet;
@@ -1622,3 +1627,24 @@ int cmd_switch(int argc, const char **argv, const char *prefix)
16221627
FREE_AND_NULL(options);
16231628
return ret;
16241629
}
1630+
1631+
int cmd_restore(int argc, const char **argv, const char *prefix)
1632+
{
1633+
struct checkout_opts opts;
1634+
struct option *options = NULL;
1635+
int ret;
1636+
1637+
memset(&opts, 0, sizeof(opts));
1638+
opts.dwim_new_local_branch = 1;
1639+
opts.switch_branch_doing_nothing_is_ok = 0;
1640+
opts.accept_pathspec = 1;
1641+
1642+
options = parse_options_dup(options);
1643+
options = add_common_options(&opts, options);
1644+
options = add_checkout_path_options(&opts, options);
1645+
1646+
ret = checkout_main(argc, argv, prefix, &opts,
1647+
options, restore_usage);
1648+
FREE_AND_NULL(options);
1649+
return ret;
1650+
}

command-list.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,7 @@ git-replace ancillarymanipulators complete
151151
git-request-pull foreignscminterface complete
152152
git-rerere ancillaryinterrogators
153153
git-reset mainporcelain worktree
154+
git-restore mainporcelain worktree
154155
git-revert mainporcelain
155156
git-rev-list plumbinginterrogators
156157
git-rev-parse plumbinginterrogators

git.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -558,6 +558,7 @@ static struct cmd_struct commands[] = {
558558
{ "replace", cmd_replace, RUN_SETUP },
559559
{ "rerere", cmd_rerere, RUN_SETUP },
560560
{ "reset", cmd_reset, RUN_SETUP },
561+
{ "restore", cmd_restore, RUN_SETUP | NEED_WORK_TREE },
561562
{ "rev-list", cmd_rev_list, RUN_SETUP | NO_PARSEOPT },
562563
{ "rev-parse", cmd_rev_parse, NO_PARSEOPT },
563564
{ "revert", cmd_revert, RUN_SETUP | NEED_WORK_TREE },

0 commit comments

Comments
 (0)