--dry-run option in git checkout

£可爱£侵袭症+ 提交于 2019-12-21 07:13:34

问题


I use git checkout --<dir_name(or)file_name> to discard all my changes in the specific directory or in the file. Whenever I do that, GIT checks-out the directory (or) file from the repository.

Is there a way I can tell GIT?, "do not override the changes, just tell me what would happen."

Similar to git clean -n (or) git clean --dry-run.

UPDATE: Before I execute, git checkout --src/, I would like to see what are the files would be overridden. I know we can use git status src/. But, wouldn't it be great to have git checkout -n --src/? Not much command changes for the user.


回答1:


You can run

$ git checkout --patch -- <files>

and it will ask for each difference whether you want to "check out" that difference. If you say no for each prompt, then it leaves it untouched.




回答2:


The Git checkout command does not have a dry-run (or similar) option. However, you can use the Git ls-files command to see which working directory files differ from HEAD:

git ls-files -dm -- src/

This will list all files which have been deleted or modified, the files that would typically be overwritten by a checkout.

Another option is to use the Git diff command:

git diff --name-only HEAD -- src/

This lists all files which differ from HEAD and would be replaced on a checkout.

If this is something that would be done often, you may want to create an alias:

git config --global alias.lco "diff --name-only HEAD"

Then you can use:

git lco -- src/



回答3:


You want a dry-run option for any command, regardless of the supposed idea that "you don't need a dry-run for checkout because you can get a list of differences other ways".

You don't want a dry-run option to get a list of differences, you want a dry-run to verify "What will happen when I press enter?" before you do it for real. There is a difference. You are testing the actual/exact behavior of a program when there might be some ambiguity if all you did was read the manual.

I have a strange project where the repo is based right in '/'. So, there is a '/.git' directory and '/.gitignore' and '/.gitmodules' files. The /.gitignore and /.gitmodules files are tracked in the repo, and that's a problem because even if the developer user has permission to edit the file, they still don't have permission for git to delete and re-create the file, because the don't and can't, have write permission on '/' itself. If git edited files in-place there would be no problem, but git deletes and replaces, because a user gets an error that git couldn't unlink the file. In the course of developing a change to our repo config, and some directions for developers follow to remove this problem in the future, along the way I want to know what will this command do:

git checkout master -- /.git*

and other possible variations like

git checkout master -- '/.git*'

and others, changing the shell globbing and/or seeing how git itself might interpret the final filespec value. If I escape a '*' from the shell, will git expand a '*', or will it treat it as a literal? If it expands it, would it include the '/.git/' dir? If it expands it, is there some regex syntax I could use that means 'any-single-non-empty-character' like a '.' in regex or a '?' in shell globbing? etc etc

I don't want to know what files are different, I want to test the exact behavior of git to find the best/simplest version of an unusual command or set of commands.

For that, you really want a dry-run option. I already know what files are different. In this case, MANY files would be different, and I don't want any of them. I just want /.gitignore and /.gitmodules and nothing else.

In this case, I know I can do that by simply specifying them both explicitly on the command line.

git checkout master -- /.gitignore /.gitmodules

But I want to see if there is a shorter globbing syntax that will get them both automatically, yet ideally, NOT include the /.git directory. And ideally, I'd like to work out what the simplest form is I can get away with. I know I could use the shell to do some fancy and very specific expansion, but if something like '/git*' works, I'd rather use that than '/git{i,m}*'

This particular task is small and has several simple answers. Please don't tell me ways to solve THIS EXACT PROBLEM without "git checkout --dry-run", or tell me how stupid it was to make a repo in /, I know that too. I already know several ways to get my immediate job done. That's not the point. It could have easily involved more files or a more complicated globbing pattern such that it wouldn't have been so convenient to just list the files explicitly, or, it might have been some completely different type of problem.

The point is, in general, applies to any command anywhere, including git checkout, there is always a use for a dry-run option to test the behavior of a program itself. Reading the manual or --help does not answer the question answered by dry-run.




回答4:


Not sure but as a work around could you not git stash -u then git apply then git checkout?

You can always revert back to the stash if you are unhappy.




回答5:


If you want to avoid interactivity (a la "say no to each prompt"), use git diff. If you want an exact answer to your question, use git diff -R. If you just want file names, use git diff --name-only.

Without the -R flag, git diff will report all the differences between your working tree and your index in a patch format, i.e. the format you see when you issue git show <commit>. The -R reverses the output, showing you what would happen were the changes removed, as if the removal were itself a patch. Consider an example:

git init /tmp/test && cd /tmp/test
echo "old line">file
git add .
git commit -m "Initial commit"
echo "new line">file

Now issue git diff without any flags. You should get:

$ git diff
diff --git a/file b/file
index 0906fba..86ba82a 100644
--- a/file
+++ b/file
@@ -1 +1 @@
-old line
+new line

Frankly, I find that output easy enough to parse I never use the -R flag. If you routinely issue git diff commands (and I find it to be one of the most common commands I use), reversed output is likely not necessary. All the same, for the purposes of this answer, try:

$ git diff -R
git diff -R
diff --git b/file a/file
index 86ba82a..0906fba 100644
--- b/file
+++ a/file
@@ -1 +1 @@
-new line
+old line

That output exactly describes what you seek: "do not override the changes, just tell me what would happen."

By default, that command will diff your entire working directory with the index. It'll show you the diffs in every modified file. Suppose you just want to see the effect on one file. That's easy. Just use the same double-dash nomenclature you're already using:

git diff -- <file>

You'll find git diff to be one of the most useful, extensible commands in git, and you can use it to do all sorts of helpful things. You can use it to compare two commits, two branches, or two files. My most recent "favorite crazy git operation" is piping git diff to git apply. The former produces intelligible patches. The latter applies them. Your ability to rewrite history when they are combined is nigh limitless -- locally of course, never rewrite shared history. Consider another example, at this point off topic but seriously entertaining (if you're into this kind of thing). From our test repository, above:

git add .
git commit -m "Second commit"
echo "even newer line">file
git add .
git commit -m "Third commit"

You know what? I didn't like that second commit much. Its implementation was buggy. It is breaking tests. I don't want to share it. Nevertheless, I do want to keep the "Second commit" commit message because that was really hard to type. I could rebase it out with git rebase -i HEAD~2, but that involves opening the editor, deleting a commit, editing another and (ugh) copy/paste. What is a dev to do? How about this:

git checkout ":/Initial" ;# get back to the first commit
git diff HEAD ":/Third" | git apply ;# apply the diff between the first and third commit
git add . ;# add the result
git commit -C ":/Second" ;# with second commit's message
git checkout -B master HEAD ;# and replace old 'master'

The result is the same as it would be with git rebase. I just managed to avoid interactive sessions and I didn't have to use the editor. Is it overkill? Probably, but it sure is fun. Moreover, it's easy to construct far more complicated use cases, particularly when you combine git diff, git apply, and git add -p.



来源:https://stackoverflow.com/questions/11306737/dry-run-option-in-git-checkout

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!