mail

How to view staged changes ?

mail

How to unstage a file ?

To "unstage" a file means "remove it from the index (aka staging area)". To do so :

git reset HEAD path/to/file

mail

How to stage / unstage a patch ?

Solution 1 : interactive staging (source) :

  1. Enter Git interactive staging : git add -i (or git add --interactive)
  2. Type p for patch
  3. Type the number of the file you'd like to take a patch from, then (twice : ???)
  4. This will display the hunks of the current file and offer keys :
    • y (yes) : stage this hunk
    • n (no) : do not stage this hunk
    • a (all) : stage this and all the remaining hunks in the file
    • d (don't) : do not stage this hunk nor any of the remaining hunks in the file
    • ? (help)
  5. When all the desired changes are staged, leave with q
  6. If something went wrong while staging changes, you can unstage some changes
  7. Then commit the staged changes : git commit -m 'What a beautiful commit'

Solution 2 : git add in patch mode : -p / --patch (source 1, 2) :

git add --patch myFile, then for each hunk :

  • y (yes) : stage this hunk
  • n (no) : do not stage this hunk
  • a (all) : stage this and all the remaining hunks in the file
  • d (don't) : do not stage this hunk nor any of the remaining hunks in the file
  • s (split) : split the current hunk into smaller hunks
  • / : search for a hunk matching the given regex
  • ? (help)
  • (there are more )
This -p option is a shortcut to the -i above + patch.

It is possible to do the opposite; i.e. interactively select hunks to unstage with git reset -p.

BONUS : How to stage a patch while having contiguous changed lines (source) ?

Let's start by simulating the situation :

  1. Create the Git repo, add some code and commit : myDir=~/testDir; myFile='testFile'; mkdir "$myDir"; cd "$myDir"; git init; echo 'line 1' >> "$myFile"; git add "$myFile"; git commit -m 'Initial version'
  2. Improve the code : echo -e "line 2\nline 3" >> "$myFile"
  3. Our program now looks like : cat "$myFile"
    line 1
    line 2
    line 3
  4. And Git sees some difference : git diff
    diff --git a/testFile b/testFile
    index 89b24ec..a92d664 100644
    --- a/testFile
    +++ b/testFile
    @@ -1 +1,3 @@
     line 1
    +line 2
    +line 3

And the question is : how may I stage line 2 split from line 3 so that I can make 2 separate commits ?

  • With git add --patch, the split command is useless since the changed lines are contiguous
  • Still with git add --patch, the regex search function doesn't work so far (returns all lines, whatever pattern I enter)

Now the solution :

  1. Prepare to stage changes in patch mode : git add --patch
    diff --git a/testFile b/testFile
    index 89b24ec..a92d664 100644
    --- a/testFile
    +++ b/testFile
    @@ -1 +1,3 @@
     line 1
    +line 2
    +line 3
    Stage this hunk [y,n,q,a,d,/,e,?]?
  2. Then type e to edit the hunk. This will open your default text editor
  3. Once in the editor, follow the instructions to specify which lines to stage or not :
    # Manual hunk edit mode -- see bottom for a quick guide
    @@ -1 +1,3 @@
     line 1
    +line 2
    #+line 3
    # ---
    # To remove '-' lines, make them ' ' lines (context).
    # To remove '+' lines, delete them.
    # Lines starting with # will be removed.
    #
    # If the patch applies cleanly, the edited hunk will immediately be
    # marked for staging. If it does not apply cleanly, you will be given
    # an opportunity to edit again. If all lines of the hunk are removed,
    # then the edit is aborted and the hunk is left unchanged.
    To not stage a ... line Do :
    +
    • add a leading #
    • OR delete this line
    - change the leading - into a [SPACE]
    Save and exit.
    If you're using Emacs and this step fails saying things like patch fragment without header and Your edited hunk does not apply, read this.
  4. View staged changes : git diff --staged
    diff --git a/testFile b/testFile
    index 89b24ec..7bba8c8 100644
    --- a/testFile
    +++ b/testFile
    @@ -1 +1,2 @@
     line 1
    +line 2
  5. Commit. Enjoy.
mail

How to save a WIP ?

You may have to save a WIP (i.e. changes made after the previous commit are not ready for a new commit yet) before changing branch. To do so :
  1. git stash
  2. git status should return no modified file
  3. create a new branch "newBranch", work hard, commit
  4. come back to the original branch : git checkout previousBranch
  5. restore WIP in previousBranch : git stash apply
  6. OR drop "stashed" content : git stash drop
mail

How to discard local uncommitted changes ?

If you need to unstage changes first :
git reset
Undo all local uncommitted changes :
Undo local uncommitted changes for a specific file :
git checkout someFile
mail

How to create and apply a patch ?

To proceed, you must have a few commits and a distant copy/clone/remote of your repository. To make things even easier, it's a good practice to create a dedicated branch for a fix / new feature.
  1. Create a patch containing changes between the current status and the branch master : git format-patch master --stdout > theNameOfMy.patch
  2. You can inspect the patch with your favorite text editor. Send it to whoever needs it. The following steps take place on the "patch receiver" side
  3. List changes provided by the patch : git apply --stat theNameOfMy.patch
  4. Check/dry-run the patch : git apply --check theNameOfMy.patch
  5. If the previous command output no error, you can now apply the patch : git am --signoff < theNameOfMy.patch
  6. Check the logs : git log will output
    commit 7d7a786c1353b5433b7e39a6b50c7ac8d9b5159f
    Author: Thomas ANDERSON <thomas.anderson@metacortex.com>	who made the commit
    Date:	Fri Jul 18 09:35:36 2014 +0200
    
    	Fixed a glitch in the Matrix
    
    	Signed-off-by: Smith <smith@thematrix>		who applied the patch