Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

I'm rather new to the broad world of Git. I have read the manual and have been practicing but I am confused about few aspects of it, which I couldn't figure out after searching for.

I'm wondering:

  • In a project (post first commit), when is the right moment to stage source files? Right before committing? Right after adding/deleting or modifying?

  • If files are staged midway between two commits, and then they get modified, what happens with Git? Does it need care about content changes when it was stated and what it become since?

  • If I create a new file, stage it and then want to delete it, why does Git ask me to use "-f" flag and a simple "git -rm file.ext" won't work?

I have read "What stage means" and various other subjects of the manual and other tutorials on Git but as I said, I still don't understand the above matters.

So, if you could, please answer the questions with your own words and examples so I might have a better chance of understanding it.

Thank you.

share|improve this question
1  
I stage files whenever I finished some small piece of work (too small for a commit) or before some changes I'm not sure about. Do whatever works for you. Find a tool (e.g., git gui or git cola) showing you both the stages and unstaged changes (git diff and git diff --cached are good, but sometimes I want more). –  maaartinus Sep 9 '13 at 12:55

2 Answers 2

The purpose of the staging area is to have a flexible space for your commit. I think this will become clearer if you contrast git to version control systems that are centralized, such as subversion.

Subversion

In subversion you can select to commit certain files of your working copy. But only the complete files. Now: What if you want to stage file A, not file B, and the parts of file C that relate to file A yet not the parts that depend on changes in file B (since then you would have a problem with commit consistency).

Git

Git solves this by providing the staging are as second working copy. Within the staging area you are putting together a snapshot that you will commit (roughly speaking).

Therefore within the staging area you can create a snapshot that includes changes to A and a version of file C which only reflects the changes in A.

For the specific questions

  • You can stage at any point you want. i personally prefer to stage right before I launch the commit.

  • When having changes in a file staged and then changing that file in the working copy, you have not altered the staged file of course. You can either decide whether to stage those as well or whether not to stage thos changes. I.e. if you run git gui citool you will see diffs of staged and unstaged versions (nice and simple tools for line-wise staging and committing).

  • Git is cautious here, which is probably a good thing.

General commit strategy: Granular commits

I think when talking about the question "When should I stage", one should also talk about commit habits.

Centralized VCS

In centralized version control systems where you commit to a central server, it was important for you co-workers that your commits are complete and well-tested. So people would try to commit not-so-often and then commit the state of complete files to minimize the possibility of an error. Thus, a commits tend to be quite large chunks which include lots of changes (if they are not simple fixes). The changes in a commit can be totally unrelated.

Git

In Git a commit is performed locally, only pushing them out to a server makes them public. Therefore a commit is cheap in a sense. A commit in the subversion sense is rather comparable to several git commit followed by git push. This difference matters.

Git allows you to commit single lines of code, even if you have changed other lines in the same file as well. This gives you a lot of benefits since you can for example commit a security bugfix in line 100 while having changed lines 300-350 introducing a new feature.

  • You can separate different changes in different commits. This separates them nicely in your version history and even allows you to revert one but not the other.
  • Your commit does not necessarily have to reflect a "compiling" state of your working copy (although I try to keep it that way).

So where is the "quality control" and build-guarantee in a commit that a subversion user would expect? It is shifted to other actions in git. You still want to push out a functioning state of the program in a public repository. Therefore you make sure that tests are successful and the program works before pushing out your changes.

Also, try to utilize branches to the max. When commiting lots of small changes you will end up with a pretty big version history. If you work in branches, you can categorize those granular commits by the branch name and then merge them back (option --no-ff will also preserve that these features lived in a unique branch).

I.e. you can keep the habit of merging to the master branch only, if the branch is in a good state. You can also use tags to track milestones and releases.

Now to come back to staging: Once you commit a few lines per commit, you will stage directly before commiting. (At least that is how I do it).

share|improve this answer
    
git add -p is so very nice. –  Vorac Sep 9 '13 at 10:54

I think you are taking it too seriously. Staging is just selecting the stuff you want to include in the next commit. It is very rarely important when or how you do the staging; and if you have a lot of staged and unstaged changes at any given moment, you probably need to revise your development process.

In a project (post first commit), when is the right moment to stage source files? Right before committing? Right after adding/deleting or modifying?

I usually do it right before committing (unless I notice some typo, so I have to make a last-moment correction and stage it too). The process is the following: edit, run tests, stage, commit. If you stage before the testing, chances are the tests will fail and you will have to make changes and stage them too, so why not leave it until the commit time?

If files are staged midway between two commits, and then they get modified, what happens with Git? Does it need care about content changes when it was stated and what it become since?

It will show you the diff between the current state of the repo and (last commit + staged changes). When you stage some of the new changes, it will just recalculate the (last commit + staged changes) state.

If I create a new file, stage it and then want to delete it, why does Git ask me to use "-f" flag and a simple "git -rm file.ext" won't work?

Now I'm guessing here, but it's probably because the staged info may be important (otherwise you wouldn't stage it), but it's not yet under version control (like a file you can remove with git -rm). So git wants to make sure you know what you are doing.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.