gitsnapshotstaging

Git staging and snapshots


I recently forgot to pull the most recent version of my remote to my local before I made a commit. No big deal I'll just stash my changes then pull from remote. This resulted in a conflict with one of the files, and I also noticed that many other files were staged. So I resolved the conflict and then removed all the files from the staging area (I didn't know anything about them) except the file that I resolved the conflict on, lastly, I committed and pushed what I thought was that single file.

Turns out my understanding of how git works is flawed, and I pushed the snapshot of my local workspace (without the many other files from the remote that I was trying to fetch and merge). This effectively removed those files from the remote branches new head (my commit)

My guess is these questions have been asked before but I wasn't able to find them so here goes:

Is staging files required? If git just commits a snapshot of your whole local workspace anyway, why index anything? Lastly is there a command (I could create an alias) that wraps pull and commit, so that I don't forget to pull before committing again, so it would fetch, merge, commit? Or is there a reason the command doesn't exist?


Solution

  • When you do a git commit you record a snapshot of the whole working directory, but not necessary your working directory.

    That is you can have a lot of changes in a lot of files and only include in a commit a few of these changes. That does not mean that those other files are not part of the commit: technically all unchanged files are part of that commit, they are just not part of the commit diff.

    The index, or stage, is useful to prepare the status of the working directory you are going to commit. If you do not need that and just want to commit anything changed, you can just do git commit -a. That will not add new files, only changed ones. If you want to add also all the new files, you can do git commit -au.

    About your previous mess. That is actually pretty easy once you know the basic rule. The basic rule for git is: when in doubt, commit.

    How would have worked in your case? Let's see:

    1. You forget to pull and work a little.
    2. Do git commit! To your local master branch, of course.
    3. Do git push and it fails because you the remote branch has advanced.
    4. Do git fetch to get the latest changes.
    5. Do git merge or git rebase to mix your changes with those from origin.
    6. If there are conflicts, solve them and git merge/rebase --continue.
    7. Do git push and profit!

    The only chance of breaking things is when solving conflicts. If that happens, a git merge/rebase --abort restores you to the last good commit.

    About a command that does everything... beware! git pull is already a mix of git fetch plus git merge (or git rebase). It may save you some time, but if you are learning git I very much recommend not to use git pull but do the other two commands separately.

    Doing a git commit and a git pull and a git push all at the same time will be probably quite a bad idea.