--cached means show the changes in the cache/index (i.e. staged changes) against the current HEAD. --staged is a synonym for --cached.
--staged and --cached does not point to HEAD, just difference with respect to HEAD. If you cherry pick what to commit using git add --patch (or git add -p), --staged will return what is staged.
git-clean - Remove untracked files from the working tree
Cleans the working tree by recursively removing files that are not under version control, starting from the current directory.
-d
Remove untracked directories in addition to untracked files. If an untracked directory is managed by a different Git repository, it is not removed by default. Use -f option twice if you really want to remove such a directory.
-f
--force
If the Git configuration variable clean.requireForce is not set to false, git clean will refuse to delete files or directories unless given -f, -n or -i. Git will refuse to delete directories with .git sub directory or file unless a second -f is given.
-i
--interactive
Show what would be done and clean files interactively. See “Interactive mode” for details.
-n
--dry-run
Don’t actually remove anything, just show what would be done.
-x
Don’t use the standard ignore rules read from .gitignore (per directory) and $GIT_DIR/info/exclude, but do still use the ignore rules given with -e options. This allows removing all untracked files, including build products. This can be used (possibly in conjunction with git reset) to create a pristine working directory to test a clean build.
-X
Remove only files ignored by Git. This may be useful to rebuild everything from scratch, but keep manually created files.
What you need to do is to create a new commit with the same details as the current HEAD commit, but with the parent as the previous version of HEAD. git reset --soft will move the branch pointer so that the next commit happens on top of a different commit from where the current branch head is now.
# Move the current head so that it's pointing at the old commit
# Leave the index intact for redoing the commit.
# HEAD@{1} gives you "the commit that HEAD pointed at before
# it was moved to where it currently points at". Note that this is
# different from HEAD~1, which gives you "the commit that is the
# parent node of the commit that HEAD is currently pointing to."
git reset --soft HEAD@{1}
# commit the current tree using the commit details of the previous
# HEAD commit. (Note that HEAD@{1} is pointing somewhere different from the
# previous command. It's now pointing at the erroneously amended commit.)
git commit -C HEAD@{1}
I want to merge the different branch into mine, and I don't care if those files are no longer ignored or not.
Unfortunately I get this:
The following untracked working tree files would be overwritten by merge
How would I modify my pull command to overwrite those files, without me having to find, move or delete those files myself?
The problem is that you are not tracking the files locally but identical files are tracked remotely so in order to "pull" your system would be forced to overwrite the local files which are not version controlled.
Try running
git add *
git stash
git pull
This will track all files, remove all of your local changes to those files, and then get the files from the server.
You can think of the HEAD as the "current branch". When you switch branches with git checkout, the HEAD revision changes to point to the tip of the new branch.
You can see what HEAD points to by doing:
cat .git/HEAD
In my case, the output is:
$ cat .git/HEAD
ref: refs/heads/master
HEAD
The current branch. In more detail: Your working tree is normally derived from the state of the tree referred to by HEAD. HEAD is a reference to one of the heads in your repository, except when using adetached HEAD, in which case it directly references an arbitrary commit.
Both ~ and ^ on their own refer to the parent of the commit (~~ and ^^ both refer to the grandparent commit, etc.) But they differ in meaning when they are used with numbers:
~2 means up two levels in the hierarchy, via the first parent if a commit has more than one parent
^2 means the second parent where a commit has more than one parent (i.e. because it's a merge)
These can be combined, so HEAD~2^3 means HEAD's grandparent commit's third parent commit.
HEAD^ means the first parent of the tip of the current branch.
Remember that git commits can have more than one parent. HEAD^ is short for HEAD^1, and you can also address HEAD^2 and so on as appropriate.
You can get to parents of any commit, not just HEAD. You can also move back through generations: for example, master~2 means the grandparent of the tip of the master branch, favoring the first parent in cases of ambiguity. These specifiers can be chained arbitrarily , e.g., topic~3^2.
A suffix ^ to a revision parameter means the first parent of that commit object. ^<n> means the <n>th parent (i.e. <rev>^ is equivalent to <rev>^1). As a special rule, <rev>^0 means the commit itself and is used when <rev> is the object name of a tag object that refers to a commit object.
<rev>~<n>, e.g. master~3
A suffix ~<n> to a revision parameter means the commit object that is the <n>th generation ancestor of the named commit object, following only the first parents. I.e. <rev>~3 is equivalent to <rev>^^^ which is equivalent to <rev>^1^1^1. See below for an illustration of the usage of this form.
HEAD is (direct or indirect, i.e. symbolic) reference to the current commit. It is a commit that you have checked in the working directory (unless you made some changes, or equivalent), and it is a commit on top of which "git commit" would make a new one. Usually HEAD is symbolic reference to some other named branch; this branch is currently checked out branch, or current branch. HEADcan also point directly to a commit; this state is called "detached HEAD", and can be understood as being on unnamed, anonymous branch.
And @ alone is a shortcut for HEAD, since Git 1.8.5
ORIG_HEAD is previous state of HEAD, set by commands that have possibly dangerous behavior, to be easy to revert them. It is less useful now that Git has reflog: HEAD@{1} is roughly equivalent to ORIG_HEAD (HEAD@{1} is always last value of HEAD, ORIG_HEAD is last value of HEAD before dangerous operation).
"pull" or "merge" always leaves the original tip of the current branch in ORIG_HEAD.
git reset --hard ORIG_HEAD
Resetting hard to it brings your index file and the working tree back to that state, and resets the tip of the branch to that commit.
Instead of typing four capital letters "HEAD", you can say "@" now,
e.g. "git log @".
Typing 'HEAD' is tedious, especially when we can use '@' instead.
The reason for choosing '@' is that it follows naturally from the ref@op syntax (e.g. HEAD@{u}), except we have no ref, and no operation, and when we don't have those, it makes sens to assume 'HEAD'.
So now we can use 'git show @~1', and all that goody goodness.
HEAD means "current" everywhere in git, but it does not necessarily mean "current branch" (i.e. detached HEAD).
After inspecting the result of the merge, you may find that the change in the other branch is unsatisfactory. Running "git reset --hard ORIG_HEAD" will let you go back to where you were, but it will discard your local changes, which you do not want. "git reset --merge" keeps your local changes.
Where HEAD is literal (git shorthand for current branch name) and my/filename.js should be replaced by the actual filename of your file. This will restore your file to how it was before the update, effectively "undoing" the changes from the other person. Commit this result locally and then push as normal (no --force should be necessary if you when you have updated from the central repo)
In general, the way to resolve a merge conflict is to edit your file until it's the way you want it, and then run git add. The reason git (and svn for that matter) leave the "<<<" and ">>>" results in your file after a failed merge or update is to help you or your tools to resolve the merge. Setting up a tool to help you do this will probably be worth it, but it's a shame it doesn't come out of the box.
First clone the repo with the -n option, which suppresses the default checkout of all files, and the --depth 1 option, which means it only gets the most recent revision of each file
git rebase -i <oldsha1> opens a list of commits from oldsha1 to the latest commit in the branch. You can:
reorder them,
change the commit message of some,
squash (merge) two commits together,
and edit a commit.
We use edit in our case as we want to change the commit. Simply replace the pick word with editon the line of the commit you want to split. When you save and close this "file", you will be placed at that commit in the command line.
Undo the actual commit
If you do a git status or a git diff, you will see that git places you right after the commit. What we want is to undo the commit and place the changes in our working area.
This is what git reset HEAD^ does: reset the state to the second last commit and leave the changes of the last commit in the working area. HEAD^ means the commit at HEAD minus 1.
You can of course do that by using git rebase -i and most examples show how you can go back in time a couple of commits.
git rebase -i HEAD^4 #go back 4 commits ago
There is a nicer and more efficient to do that when you work on topic branches
git rebase -i master
That's it. Pretty stupid but, since you can put any Git object reference, why not use the object where you started to fork off? The rebase will show you all commits between master and your branch.
Invoke an editor before committing successful mechanical merge to further edit the auto-generated merge message, so that the user can explain and justify the merge. The --no-edit option can be used to accept the auto-generated message (this is generally discouraged).
You can use git rebase, for example, if you want to modify back to commit bbc643cd, run
$ git rebase --interactive 'bbc643cd^'
In the default editor, modify pick to edit in the line whose commit you want to modify. Make your changes and then commit them with the same message you had before:
$ git commit --all --amend --no-edit
to modify the commit, and after that
$ git rebase --continue
to return back to the previous head commit.
WARNING: Note that this will change the SHA-1 of that commit as well as all children -- in other words, this rewrites the history from that point forward. You can break repos doing this if you push using the command git push --force
ProTip™: Don't be afraid to experiment with "dangerous" commands that rewrite history* — Git doesn't delete your commits for 90 days by default; you can find them in the reflog:
$ git reset @~3 # go back 3 commits
$ git reflog
c4f708b HEAD@{0}: reset: moving to @~3
2c52489 HEAD@{1}: commit: more changes
4a5246d HEAD@{2}: commit: make important changes
e8571e4 HEAD@{3}: commit: make some changes
... earlier commits ...
$ git reset 2c52489
... and you're back where you started
* Watch out for options like --hard and --force though — they can discard data.
* Also, don't rewrite history on any branches you're collaborating on.
The hash is a reference to the packed object that was created in the Git object store. You can examine this object if you look in .git/objects/15/96f9db1b9610f238b78dd168ae33faa2dec15c.
The 120000 is the file mode. It would be something like 100644 for a regular file and is the mode special for links. From man git-config:
core.symlinks
If false, symbolic links are checked out as small plain files that contain the link text. git-update-index(1) and git-add(1) will not change the recorded type to regular file.
So, that's what Git does to a symbolic link: when you git checkout the symbolic link, you either get a text file with a reference to a full filesystem path, or a symlink, depending on configuration. The data referenced by the symlink is not stored in the repository.
There is an important caveat when creating symlinks that are meant to be tracked under Git. The reference path of the source file should be relative to the repository, not absolute to the machine.
# Not good for Git repositories
ln -s /Users/gio/repo/foo.md ./bar/foo.md
# Good for Git repositories
cd ./bar && ln -s ../foo.md foo.md
The reason for this is that given that a symlink contains the path to the referenced file, if the path is relative to a specific machine the link won't work on others. If it's relative to the repository itself on the other hand, the OS will always be able to find the source.
Setting your branch to exactly match the remote branch can be done in two steps:
git fetch origin
git reset --hard origin/master
If you want to save your current branch's state before doing this (just in case), you can do:
git commit -a -m "Saving my work, just in case"
git branch my-saved-work
Now your work is saved on the branch "my-saved-work" in case you decide you want it back (or want to look at it later or diff it against your updated branch).
# Resets index to former commit; replace '56e05fced' with your commit code
git reset 56e05fced
However, if you run git rebase and hit a conflict, the process will stop and exit with a nonzero status. What you could do is check the exit status of the rebase operation, and, if it is nonzero, run git rebase --abort to cancel the rebase:
I do not want to fetch every branch from origin because there are many. I just want to track a few (e.g., master) and my branches (organized under my_name sub-directory). I can do the following:
When using git clone (from GitHub, or any source repository for that matter) the default name for the source of the clone is "origin". Using git remote show will display the information about this remote name. The first few lines should show:
C:\Users\jaredpar\VsVim> git remote show origin
* remote origin
Fetch URL: git@github.com:jaredpar/VsVim.git
Push URL: git@github.com:jaredpar/VsVim.git
HEAD branch: master
Remote branches:
If you want to use the value in the script, you would use the first command listed in this answer
By default, git clone creates only one branch: the currently checked out one, generally master. However, it does create remote tracking branches for all other branches in the remote. Think of these as local copies of the remote's branches, which can be updated by fetching. They're not real local branches, as they're intended only as pointers to where the remote's branches are, not for you to work on.
If you run git branch -a you'll see all branches, local and remote. If you want to see just the remote ones, use git branch -r. If you prefer a visual history display, try gitk --all (or gitk --remotes).
git remote show origin explicitly tells you which branches are tracking which remote branches.
$ git remote show origin
* remote origin
Fetch URL: /home/ageorge/tmp/d/../exrepo/
Push URL: /home/ageorge/tmp/d/../exrepo/
HEAD branch (remote HEAD is ambiguous, may be one of the following):
abranch
master
Remote branches:
abranch tracked
master tracked
Local branches configured for 'git pull':
abranch merges with remote abranch
master merges with remote master
Local refs configured for 'git push':
abranch pushes to abranch (up to date)
master pushes to master (up to date)
git rev-parse is an ancillary plumbing command primarily used for manipulation.
One common usage of git rev-parse is to print the SHA1 hashes given a revision specifier. In addition, it has various options to format this output such as --short for printing a shorter unique SHA1.
There are other use cases as well (in scripts and other tools built on top of git) that I've used for:
--verify to verify that the specified object is a valid git object.
--git-dir for displaying the abs/relative path of the the .git directory.
Checking if you're currently within a repository using --is-inside-git-dir or within a work-tree using --is-inside-work-tree
Checking if the repo is a bare using --is-bare-repository
Printing SHA1 hashes of branches (--branches), tags (--tags) and the refs can also be filtered based on the remote (using --remote)
--parse-opt to normalize arguments in a script (kind of similar to getopt) and print an output string that can be used with eval
Massage just implies that it is possible to convert the info from one form into another i.e. a transformation command. These are some quick examples I can think of:
a branch or tag name into the commit's SHA1 it is pointing to so that it can be passed to a plumbing command which only accepts SHA1 values for the commit.
a revision range A..B for git log or git diff into the equivalent arguments for the underlying plumbing command as B ^A
In the working copy view there is a dropdown where you can select a filter for the visible files in the column below. Just select "All Files" instead of the "Pending" default.
On the right side there also is a Searchbox to filter this file list.
This will grep through all your commit text for regexp.
The reason for passing the path in both commands is because rev-list will return the revisions list where all the changes to lib/util happened, but also you need to pass to grep so that it will only search on lib/util.
Just imagine the following scenario: grep might find the same <regexp> on other files which are contained in the same revision returned by rev-list (even if there was no change to that file on that revision).
The choice of '!' for a negative pathspec ends up not only not matching what we do for revisions, it's also a horrible character for shell expansion since it needs quoting.
So add '^' as an alternative alias for an excluding pathspec entry.
When working on a project you usually synchronize your code by pulling it several times a day. What you might not know is that by typing
git pull
you actually issuing git fetch + git merge commands, which will result with an extra commit and ugly merge bubbles in your commit log (check out gitk to see them).
It's much better to use
git pull --rebase
to keep the repository clean, your commits always on top of the tree until you push them to a remote server. The command will apply all your yet-to-be-pushed commits on top of the remote tree commits allowing your commits to be straight in a row and without branches (easier git bisects, yay!).
Few notes though. If you want to merge a feature branch it might be wiser to actually merge your commits thus having a single point of integration of two distinct branches.
Also the conflict resolving will be now per commit basis, not everything-at-once, so you will have to use
git rebase --continue
to get to the next batch of conflicts (if you have any).
NOTE: Because of many discussions about this note. I DO NOT encourage rebasing remote (public or shared) branches. Rebasing local history is OK (it's more than OK, it's sometimes necessary to maintain a clean history), but changing other people commits history is considered a bad practice.
It's a lot easier to just set rebase as the default using
An annotated tag creates an additional tag object in the Git repository, which allows you to store information associated with the tag itself. This may include release notes, the meta-information about the release, and optionally a signature to verify the authenticity of the commit to which it points.
We can create a simple tag, based on the current repository's version, with:
$ git tag example
This creates a lightweight tag as a reference in .git/refs/tags/example, which points to the current commit. If we want to make it as an annotated tag, we need to supply -a, and a message with -m:
$ git tag -a v1 -m "Version 1 release"
This will create an (unsigned) annotated tag object, containing that message and a pointer to the commit object. Now the reference in .git/refs/tags/v1 will point to the tag object, which then points to the commit.
What's the difference between tags and branches? The workspace is (almost always) associated with a branch, called master by default. When it is, a commit will automatically update the master reference to point to that new commit; in other words, branches are mutable references.
A tag, on the other hand, is created to point to a specific commit and thereafter does not change, even if the branch moves on. In other words, tags are immutable references.
Git provides a couple of mechanisms for identifying changes by labels instead of by unique hash values.
The first, we've already seen, is branches. When we switch between two branches, we're really using the descriptive label to identify a specific commit to switch to.
The second, which we'll introduce here, is tags. A tag is like a branch, in that it identifies a specific commit with a descriptive label.
Another way to tag commits is with a lightweight tag. This is basically the commit checksum stored in a file — no other information is kept. To create a lightweight tag, don’t supply any of the -a, -s, or -moptions, just provide a tag name:
It often happens that while working on one project, you need to use another project from within it. Perhaps it’s a library that a third party developed or that you’re developing separately and using in multiple parent projects. A common issue arises in these scenarios: you want to be able to treat the two projects as separate yet still be able to use one from within the other.
Submodules allow you to keep a Git repository as a subdirectory of another Git repository. This lets you clone another repository into your project and keep your commits separate.
By default, submodules will add the subproject into a directory named the same as the repository, in this case “DbConnector”. You can add a different path at the end of the command if you want it to go elsewhere.