Command line git question

snotnose

Ars Tribunus Militum
2,747
Subscriptor
I'm fairly new to git and most of my interaction with it has been via the IntelliJ Idea IDE. But sometimes I use a command line. In one directory I did "git init", "git add files", and "git commit". As I edit files I do more commits, things are good. Except:
Code:
309 -=> git status
On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
        modified:   Notes
        modified:   Starweb.sav
        modified:   map330.odg

Untracked files:
  (use "git add <file>..." to include in what will be committed)
        .~lock.map330.odg#
        Starweb.jar
        foo
        t0.txt
        t1.txt
        t2.txt
        t3.txt
        t4.txt

no changes added to commit (use "git add" and/or "git commit -a")
310 -=> git commit -m "no meaningful changes, this is a git test"
On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
        modified:   Notes
        modified:   Starweb.sav
        modified:   map330.odg
Every time I want to commit these 3 files I have to re-add them. Why?
 

Ardax

Ars Legatus Legionis
19,076
Subscriptor
If you're using the command line, you have to stage the changes (adds, edits, or deletes) you want to commit to the index. The commit command creates the new commit based on the contents of said index, your commit message, and the previous commit.

NDP's Git Cheatsheet is a good visual guide to the different areas and the commands that work with them.

Edit: no changes added to commit (use "git add" and/or "git commit -a") is the hint you need to pay attention to.
 

Jonathon

Ars Legatus Legionis
16,541
Subscriptor
git commit -a may be what you're looking for
And then you can find out (the hard way) why git add is a manual operation by default, when you commit something you didn't mean to (like temporary debug/test code, or unfinished work in a different part of your codebase).

git commit -a is fine as a shortcut if you're paying attention to what you're doing. But there is a reason why stage-then-commit exists as a two-step process.
 

OrangeCream

Ars Legatus Legionis
55,362
You seem to be calling git commit without calling git add; the fact that those 3 files show they are modified means your changes aren't being tracked. General workflow:
  • edit Starweb.sav; will show in git status as modified, not staged for commit
  • git add Starweb.sav; will show as modified, to be committed
  • git commit; will prompt you for a commit message, and then save your change to the respository
  • git status will no longer show Starweb.sav as being modified
 

koala

Ars Tribunus Angusticlavius
7,579
Even if you are very careful with gitignore and other stuff, it's still quite easy to commit things inadvertently. Just today we hit a couple of times pushing stuff we shouldn't have (because a tool we use lacks some features and we need to edit manually files temporarily).

I always recommend git commit -v, and never using git commit -m, because I feel it helps you work better.

But really, if you're not making a ton of mistakes frequently, git commit -a can be fine. Although I always combine it with -v, and it's still a bit error-prone (e.g. when you use it constantly, it's very easy to forget to add new files).

(Also, a new teammate is using https://martinvonz.github.io/jj/ and it might be the thing that pushes me to try it out. Although apparently, it has some limitations related to the issues in this post.)
 
  • Like
Reactions: lukem

snotnose

Ars Tribunus Militum
2,747
Subscriptor
Ahh, I misunderstood the -a flag. However, I often run across stuff like:
Sometimes, when you make small changes, using the staging environment seems like a waste of time. It is possible to commit changes directly, skipping the staging environment. The -a option will automatically stage every changed, already tracked file.
Using the staging area like this is exactly what I've done for 40 yearrs, starting with RCS. I stick files into VCS, edit them, and check in the changes.

I'm clearly missing something fundamental about git. FWIW, I don't have a remote repository so push/pull don't apply to me. At least I don't think they do.
 

koala

Ars Tribunus Angusticlavius
7,579
I did use cvs for quite a few years, but apparently, I've forgotten how it works :D

cvs add seems similar to git add, but I believe they don't behave identically.

I always think of the Git index as an innovation that was not present in neither Subversion nor CVS, which I used before Git. All commits are created from the index, where you must add the changes explicitly that you want to commit.

This allows magic like git add -p, which you can use to stage parts of files, allowing you to prevent parts of the file from being committed. I think neither cvs or Subversion had this.

(Edit: and yes, this is entirely independent of remotes.)
 
  • Like
Reactions: lukem

Jonathon

Ars Legatus Legionis
16,541
Subscriptor
Ahh, I misunderstood the -a flag. However, I often run across stuff like:

Using the staging area like this is exactly what I've done for 40 yearrs, starting with RCS. I stick files into VCS, edit them, and check in the changes.

I'm clearly missing something fundamental about git. FWIW, I don't have a remote repository so push/pull don't apply to me. At least I don't think they do.
Git makes a distinction between your working copy (the files that exist on disk, that you're directly editing with IntelliJ or VS Code or vim or whatever) and its staging area (the "index" in Git terminology, which, frankly, is kind of an awful term for what it is-- this is the tree that will be included in your next commit whenever you do git commit). If you're familiar with older VCSes like SVN or CVS (or even some modern ones like Mercurial), this is a distinction that doesn't really exist there.

So, to make a change to a file in Git (or to add a new file-- same workflow either way), you make your edits. Then you stage it (or add it to the index), with git add. Then you do git commit, which takes everything that you've staged (everything in the index), bundles it up with commit message, author, timestamp, parent commit(s), etc., makes a commit out of it, and adjusts all the pointers to make that the latest commit (on your current branch) in the Git repository. Repeat ad infinitum.

git commit -a does the git add bit for you (it's a single-step automatic stage-then-commit), with the distinction that it only does it for files that Git is already tracking-- it won't catch new files.

If you want a free resource on what's actually going on here, the Chacon/Straub Pro Git is good, comprehensive, and free: https://git-scm.com/book/en/v2

For something shorter, Julia Evans just put out a How Git Works zine that should hit the high points pretty accessibly-- I haven't picked it up yet myself, but I know she spent a lot of time working to nail down exactly where potential readers were in terms of Git understanding. And her other stuff's good.
 
Last edited:

Ardax

Ars Legatus Legionis
19,076
Subscriptor
I'm clearly missing something fundamental about git.

The fundamental change is that there's a virtual layer between the workspace (a.k.a. working tree, "files on disk") and the repository -- this layer is called the index or staging area.

git add adds things to the index. git commit creates a new commit using the things in the index.

So yeah, you have to call "git add" every time you edit a file. Barring the use of some shorthand like git commit -a. Even that doesn't pick up newly added files as others have pointed out.

I'm not sure what other VCS have used such a concept.
 
  • Like
Reactions: continuum

koala

Ars Tribunus Angusticlavius
7,579
cvs - a version control system that replaced RCS
VCS - Version Control System. RCS, CVS, ClearCase, Perforce, git, etc.

Not sure if you misread what I said or not.
I meant CVS.

(In my first programming job, we had a Windows share with the source code, and people would duplicate files before editing them to keep track of history. At some point, we moved to CVS, and it was a huge advancement. But I still remember the nightmares I had because we decided to work on master and a parallel branch for a long time, and I had to take care of the merge.)

Actually, this is why I remember cvs add and git add are different. I remember having to adapt to that, although I cannot remember the specifics of how cvs add worked- it doesn't match 100% my recollection.
 

Mark086

Ars Tribunus Angusticlavius
10,595
Occasionally you're going to want to commit only some of the files that have changed. Git add is a nice feature, if seemingly redundant.

I usually do a git status at the start of my commit process. I review the list of identified files, I usually add all of them, occasionally I'll leave a couple out of the commit. Sometimes the changes to those files were experimental or diagnostic. (Since I use a scripting language, not a compiled language)

Sometimes I do git diff to compare the actual line changes to my expectations.

Then I do a commit add for all the files I want to commit. You can hit add each file on the same command line, or one per each.

Then I do a commit.

Then, particular when I'm getting paranoid, I compare the last commit with the prior by doing a diff and reviewing the actual changes committed.

Then I push it remotely and go add notes to the merge request that I generate and submit in gitlab.

I usually review the merge request in the web browser and review the changes there as well.
 

Lt_Storm

Ars Praefectus
16,294
Subscriptor++
I'm fairly new to git and most of my interaction with it has been via the IntelliJ Idea IDE. But sometimes I use a command line. In one directory I did "git init", "git add files", and "git commit". As I edit files I do more commits, things are good. Except:
Code:
309 -=> git status
On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
        modified:   Notes
        modified:   Starweb.sav
        modified:   map330.odg

Untracked files:
  (use "git add <file>..." to include in what will be committed)
        .~lock.map330.odg#
        Starweb.jar
        foo
        t0.txt
        t1.txt
        t2.txt
        t3.txt
        t4.txt

no changes added to commit (use "git add" and/or "git commit -a")
310 -=> git commit -m "no meaningful changes, this is a git test"
On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
        modified:   Notes
        modified:   Starweb.sav
        modified:   map330.odg
Every time I want to commit these 3 files I have to re-add them. Why?
Because you aren't actually adding files, instead you are adding changes. It could be a new file, or just changes to a particular file, or even just changes to a couple lines but not all the changes in the file (git add -p).

This is quite helpful when, in the middle of working on something else, you need to make a slight unrelated tweak to foo.cs because of a bug report and don't want to include what you are working on. So you use:
Code:
git add foo.cs
git commit -m "bugfix XYZ in foo.cs"
git stash save
// do testing
git push
git stash pop