简体   繁体   中英

How do you commit a file without comments?

I have a file that I am in the process of working on. I have some not-yet-ready features in commented code, while everything that is not in a comment works as expected.

Is it possible to commit a file excluding its comments? Is there a better way to do this?

Using git add -p (or the patch option from git add -i ), as mentioned in a comment , is one way to do this. See also Commit only part of a file in Git and Whats the difference between git add -p and git add --patch? . Note that git add -p makes use of the fact that Git keeps, at all times, three copies of each "active" file. Let's say your file is named foo.py , for concreteness:

  • There's a version of foo.py in the current commit . This copy cannot be changed because the files stored inside commits are permanent, read-only, and—for storage reasons among others—literally shared with any other matching copy of that file. So if foo.py in this commit matches foo.py in any other commit, those commits literally share one copy of the file; changing it would affect both commits. (More precisely, it would break both, as Git makes sure during file-extraction that the hash IDs all match up, and these wouldn't.)

  • Meanwhile, there's another version of foo.py in Git's index AKA staging area . This copy can be changed: it's in the compressed-and-de-duplicated format that Git uses in commits, but it is not in a commit, so it can just be deleted and a different pre-compressed-and-de-duplicated copy installed.

  • Last, there's the version of foo.py you can open up in your editor or IDE or whatever, and work on / with. This is the only one you can see , but Git won't actually use this one to make a new commit.

Git uses the index copy to make new commits. So, git add -p will, in effect, extract the index copy, diff that against the working tree copy, and then let you add—or not add—any particular patch to the index copy. The patching works by updating the temporary copy and git add -ing that temporary copy. 1

Should you add something you don't want added, you can use git reset -p . This works by diff-ing the index (proposed new commit) copy vs the frozen-for-all-time foo.py in the HEAD commit, allowing you to "un-add" individual hunks. That is, git add -p incrementally takes the index copy towards the working tree copy, while git reset -p incrementally takes the index copy back towards the committed copy.

Sometimes, add and reset with -p are the way to go. Sometimes though this is a lot of work, and you can make use of something else: Running git add on a file copies that file, as it stands right now , into Git's index (replacing the old copy that was in the index / staging-area). So sometimes the way to handle this is to save the file in a temporary, run something—an editor, or a quick comment-stripping program you write, for instance—to weed out the stuff you don't want committed. You can then git add this copy of foo.py .

In any case, when you think it is ready, run git diff --staged -- foo.py (or just git diff --staged or git diff --cached 2 ) to observe the differences between the HEAD commit frozen-for-all-time copy, and the staged-for-commit index copy, of foo.py (or every file). That shows you what changes you will commit if you run git commit right now. Once that's the right set of changes, run git commit to make a new commit by freezing, for all time, the current contents of Git's index / staging-area. This will become the new HEAD / current commit; HEAD and Git's index will now match. Any working tree file differences are now "changes not staged for commit", including if you move a foo.py.save-comments version back at this point.


1 The original git add -p code is a Perl script that literally does exactly this. It is being, or has been, rewritten in C, but it still works the same internally.

2 There is no difference at all between git diff --cached and git diff --staged . Some commands take --staged only ( git restore ), some take --cached only ( git rm ), and some take either one ( git diff ). This is not for any good reason; it's just a historical accident. The term staging area for Git's index is the newest of the three: originally it was just the "cache" or the "index", depending on how it was being used and who wrote some bit of documentation. The term staging area reflects how you use it, so is perhaps the best of the three terms, but it does miss out on some technical aspects of the index, so I tend to use the term "index".

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