I accidentally committed the wrong files to Git, but I haven’t pushed the commit to the server yet.
How can I undo those commits from the local repository?
$ git commit -m "Something terribly misguided" # (1)
$ git reset HEAD~ # (2)
<< edit files as necessary >> # (3)
$ git add ... # (4)
$ git commit -c ORIG_HEAD # (5)
git status
, so you’ll need to add them again before committing). If you only want to add more changes to the previous commit, or change the commit message1, you could use git reset --soft HEAD~
instead, which is like git reset HEAD~
(where HEAD~
is the same as HEAD~1
) but leaves your existing changes staged.
git add
anything that you want to include in your new commit.
reset
copied the old head to .git/ORIG_HEAD
; commit
with -c ORIG_HEAD
will open an editor, which initially contains the log message from the old commit and allows you to edit it. If you do not need to edit the message, you could use the -C
option.
Beware however that if you have added any new changes to the index, using commit --amend
will add them to your previous commit.
If the code is already pushed to your server and you have permissions to overwrite history (rebase) then:
You can also look at this answer:
How to move HEAD back to a previous location? (Detached head) & Undo commits
The above answer will show you git reflog
which is used to find out what is the SHA-1 which you wish to revert to. Once you found the point to which you wish to undo to use the sequence of commands as explained above.
1 Note, however, that you don’t need to reset to an earlier commit if you just made a mistake in your commit message. The easier option is to git reset
(to unstage any changes you’ve made since) and then git commit --amend
, which will open your default commit message editor pre-populated with the last commit message.
Undoing a commit is a little scary if you don’t know how it works. But it’s actually amazingly easy if you do understand.
Say you have this, where C is your HEAD and (F) is the state of your files.
You want to nuke commit C and never see it again. You do this:
The result is:
Now B is the HEAD. Because you used --hard
, your files are reset to their state at commit B.
Ah, but suppose commit C wasn’t a disaster, but just a bit off. You want to undo the commit but keep your changes for a bit of editing before you do a better commit. Starting again from here, with C as your HEAD:
You can do this, leaving off the --hard
:
In this case the result is:
In both cases, HEAD is just a pointer to the latest commit. When you do a git reset HEAD~1
, you tell Git to move the HEAD pointer back one commit. But (unless you use --hard
) you leave your files as they were. So now git status
shows the changes you had checked into C. You haven’t lost a thing!
For the lightest touch, you can even undo your commit but leave your files and your index:
This not only leaves your files alone, it even leaves your index alone. When you do git status
, you’ll see that the same files are in the index as before. In fact, right after this command, you could do git commit
and you’d be redoing the same commit you just had.
One more thing: Suppose you destroy a commit as in the first example, but then discover you needed it after all? Tough luck, right?
Nope, there’s still a way to get it back. Type git reflog
and you’ll see a list of (partial) commit shas (that is, hashes) that you’ve moved around in. Find the commit you destroyed, and do this:
You’ve now resurrected that commit. Commits don’t actually get destroyed in Git for some 90 days, so you can usually go back and rescue one you didn’t mean to get rid of.
This took me a while to figure out, so maybe this will help someone…
There are two ways to “undo” your last commit, depending on whether or not you have already made your commit public (pushed to your remote repository):
Let’s say I committed locally, but now want to remove that commit.
git log
commit 101: bad commit # latest commit, this would be called 'HEAD'
commit 100: good commit # second to last commit, this is the one we want
To restore everything back to the way it was prior to the last commit, we need to reset
to the commit before HEAD
:
git reset --soft HEAD^ # use --soft if you want to keep your changes
git reset --hard HEAD^ # use --hard if you don't care about keeping the changes you made
Now git log
will show that our last commit has been removed.
If you have already made your commits public, you will want to create a new commit which will “revert” the changes you made in your previous commit (current HEAD).
Your changes will now be reverted and ready for you to commit:
git commit -m 'restoring the file I removed by accident'
git log
commit 102: restoring the file I removed by accident
commit 101: removing a file we don't need
commit 100: adding a file that we need
For more info, check out Git Basics - Undoing Things
I want to delete a branch both locally and remotely.
$ git branch -d remotes/origin/bugfix
error: branch 'remotes/origin/bugfix' not found.
$ git branch -d origin/bugfix
error: branch 'origin/bugfix' not found.
$ git branch -rd origin/bugfix
Deleted remote branch origin/bugfix (was 2a14ef7).
$ git push
Everything up-to-date
$ git pull
From github.com:gituser/gitproject
* [new branch] bugfix -> origin/bugfix
Already up-to-date.
What should I do differently to successfully delete the remotes/origin/bugfix
branch both locally and remotely?
Note that in most cases the remote name is origin
.
To delete the local branch use one of the following:
Note: The -d
option is an alias for --delete
, which only deletes the branch if it has already been fully merged in its upstream branch. You could also use -D
, which is an alias for --delete --force
, which deletes the branch “irrespective of its merged status.” [Source: man git-branch
]
As of Git v1.7.0, you can delete a remote branch using
which might be easier to remember than
which was added in Git v1.5.0 “to delete a remote branch or a tag.”
Starting on Git v2.8.0 you can also use git push
with the -d
option as an alias for --delete
.
Therefore, the version of Git you have installed will dictate whether you need to use the easier or harder syntax.
From Chapter 3 of Pro Git by Scott Chacon:
Deleting Remote Branches
Suppose you’re done with a remote branch — say, you and your collaborators are finished with a feature and have merged it into your remote’s master branch (or whatever branch your stable code-line is in). You can delete a remote branch using the rather obtuse syntax
Boom. No more branches on your server. You may want to dog-ear this page, because you’ll need that command, and you’ll likely forget the syntax. A way to remember this command is by recalling thegit push [remotename] :[branch]
. If you want to delete your server-fix branch from the server, you run the following:git push [remotename] [localbranch]:[remotebranch]
syntax that we went over a bit earlier. If you leave off the[localbranch]
portion, then you’re basically saying, “Take nothing on my side and make it be[remotebranch]
.”
I issued git push origin: bugfix
and it worked beautifully. Scott Chacon was right—I will want to dog ear that page (or virtually dog ear by answering this on Stack Overflow).
Then you should execute this on other machines
# Fetch changes from all remotes and locally delete
# remote deleted branches/tags etc
# --prune will do the job :-;
git fetch --all --prune
to propagate changes.
Matthew’s answer is great for removing remote branches and I also appreciate the explanation, but to make a simple distinction between the two commands:
To remove a local branch from your machine:
git branch -d {the_local_branch}
(use -D
instead to force deleting the branch without checking merged status)
To remove a remote branch from the server:
git push origin --delete {the_remote_branch}
Reference: https://makandracards.com/makandra/621-git-delete-a-branch-local-or-remote
If you want more detailed explanations of the following commands, then see the long answers in the next section.
Deleting a remote branch:
git push origin --delete <branch> # Git version 1.7.0 or newer
git push origin :<branch> # Git versions older than 1.7.0
Deleting a local branch:
git branch --delete <branch>
git branch -d <branch> # Shorter version
git branch -D <branch> # Force delete un-merged branches
Deleting a local remote-tracking branch:
git branch --delete --remotes <remote>/<branch>
git branch -dr <remote>/<branch> # Shorter
git fetch <remote> --prune # Delete multiple obsolete tracking branches
git fetch <remote> -p # Shorter
When you’re dealing with deleting branches both locally and remotely, keep in mind that there are 3 different branches involved:
X
.
X
.
origin/X
that tracks the remote branch X
.
The original poster used
which only deleted his local remote-tracking branch origin/bugfix
, and not the actual remote branch bugfix
on origin
.
To delete that actual remote branch, you need
The following sections describe additional details to consider when deleting your remote and remote-tracking branches.
Note that deleting the remote branch X
from the command line using a git push
will also delete the local remote-tracking branch origin/X
, so it is not necessary to prune the obsolete remote-tracking branch with git fetch --prune
or git fetch -p
, though it wouldn’t hurt if you did it anyway.
You can verify that the remote-tracking branch origin/X
was also deleted by running the following:
# View just remote-tracking branches
git branch --remotes
git branch -r
# View both strictly local as well as remote-tracking branches
git branch --all
git branch -a
If you didn’t delete your remote branch X
from the command line (like above), then your local repo will still contain (a now obsolete) remote-tracking branch origin/X
. This can happen if you deleted a remote branch directly through GitHub’s web interface, for example.
A typical way to remove these obsolete remote-tracking branches (since Git version 1.6.6) is to simply run git fetch
with the --prune
or shorter -p
. Note that this removes all obsolete local remote-tracking branches for any remote branches that no longer exist on the remote:
Here is the relevant quote from the 1.6.6 release notes (emphasis mine):
“git fetch” learned
--all
and--multiple
options, to run fetch from many repositories, and--prune
option to remove remote tracking branches that went stale. These make “git remote update” and “git remote prune” less necessary (there is no plan to remove “remote update” nor “remote prune”, though).
Alternatively, instead of pruning your obsolete local remote-tracking branches through git fetch -p
, you can avoid making the extra network operation by just manually removing the branch(es) with the --remote
or -r
flags:
How do I revert from my current state to a snapshot made on a certain commit?
If I do git log
, then I get the following output:
$ git log
commit a867b4af366350be2e7c21b8de9cc6504678a61b`
Author: Me <me@me.com>
Date: Thu Nov 4 18:59:41 2010 -0400
blah blah blah...
commit 25eee4caef46ae64aa08e8ab3f988bc917ee1ce4
Author: Me <me@me.com>
Date: Thu Nov 4 05:13:39 2010 -0400
more blah blah blah...
commit 0766c053c0ea2035e90f504928f8df3c9363b8bd
Author: Me <me@me.com>
Date: Thu Nov 4 00:55:06 2010 -0400
And yet more blah blah...
commit 0d1d7fc32e5a947fbd92ee598033d85bfc445a50
Author: Me <me@me.com>
Date: Wed Nov 3 23:56:08 2010 -0400
Yep, more blah blah.
How do revert to the commit from November 3, i.e. commit 0d1d7fc
?
This depends a lot on what you mean by “revert”.
If you want to temporarily go back to it, fool around, then come back to where you are, all you have to do is check out the desired commit:
Or if you want to make commits while you’re there, go ahead and make a new branch while you’re at it:
To go back to where you were, just check out the branch you were on again. (If you’ve made changes, as always when switching branches, you’ll have to deal with them as appropriate. You could reset to throw them away; you could stash, checkout, stash pop to take them with you; you could commit them to a branch there if you want a branch there.)
If, on the other hand, you want to really get rid of everything you’ve done since then, there are two possibilities. One, if you haven’t published any of these commits, simply reset:
# This will destroy any local modifications.
# Don't do it if you have uncommitted work you want to keep.
git reset --hard 0d1d7fc32
# Alternatively, if there's work to keep:
git stash
git reset --hard 0d1d7fc32
git stash pop
# This saves the modifications, then reapplies that patch after resetting.
# You could get merge conflicts, if you've modified things which were
# changed since the commit you reset to.
If you mess up, you’ve already thrown away your local changes, but you can at least get back to where you were before by resetting again.
On the other hand, if you’ve published the work, you probably don’t want to reset the branch, since that’s effectively rewriting history. In that case, you could indeed revert the commits. With Git, revert has a very specific meaning: create a commit with the reverse patch to cancel it out. This way you don’t rewrite any history.
# This will create three separate revert commits:
git revert a867b4af 25eee4ca 0766c053
# It also takes ranges. This will revert the last two commits:
git revert HEAD~2..HEAD
#Similarly, you can revert a range of commits using commit hashes:
git revert a867b4af..0766c053
# Reverting a merge commit
git revert -m 1 <merge_commit_sha>
# To get just one, you could use `rebase -i` to squash them afterwards
# Or, you could do it manually (be sure to do this at top level of the repo)
# get your index and work tree into the desired state, without changing HEAD:
git checkout 0d1d7fc32 .
# Then commit. Be sure and write a good message describing what you just did
git commit
The git-revert
manpage actually covers a lot of this in its description. Another useful link is this git-scm.com section discussing git-revert.
If you decide you didn’t want to revert after all, you can revert the revert (as described here) or reset back to before the revert (see the previous section).
You may also find this answer helpful in this case:
How to move HEAD back to a previous location? (Detached head)
Lots of complicated and dangerous answers here, but it’s actually easy:
This will revert everything from the HEAD back to the commit hash, meaning it will recreate that commit state in the working tree as if every commit since had been walked back. You can then commit the current tree, and it will create a brand new commit essentially equivalent to the commit you “reverted” to.
(The --no-commit
flag lets git revert all the commits at once- otherwise you’ll be prompted for a message for each commit in the range, littering your history with unnecessary new commits.)
This is a safe and easy way to rollback to a previous state. No history is destroyed, so it can be used for commits that have already been made public.
Working on your own and just want it to work? Follow these instructions below, they’ve worked reliably for me and many others for years.
Working with others? Git is complicated. Read the comments below this answer before you do something rash.
To revert to a previous commit, ignoring any changes:
where HEAD is the last commit in your current branch
To revert to a commit that’s older than the most recent commit:
# Resets index to former commit; replace '56e05fced' with your commit code
git reset 56e05fced
# Moves pointer back to previous HEAD
git reset --soft HEAD@{1}
git commit -m "Revert to 56e05fced"
# Updates working copy to reflect the new commit
git reset --hard
Credits go to a similar Stack Overflow question, Revert to a commit by a SHA hash in Git?.
Somebody pushed a branch called test
with git push origin test
to a shared repository. I can see the branch with git branch -r
.
Now I’m trying to check out the remote test
branch.
I’ve tried:
git checkout test
which does nothing
git checkout origin/test
gives * (no branch)
. Which is confusing. How can I be on “no branch”?
How do I check out a remote Git branch?
Jakub’s answer actually improves on this. With Git versions ≥ 1.6.6, with only one remote, you can just do:
As user masukomi points out in a comment, git checkout test
will NOT work in modern git if you have multiple remotes. In this case use
or the shorthand
Before you can start working locally on a remote branch, you need to fetch it as called out in answers below.
To fetch a branch, you simply need to:
This will fetch all of the remote branches for you. You can see the branches available for checkout with:
With the remote branches in hand, you now need to check out the branch you are interested in, giving you a local working copy:
Sidenote: With modern Git (>= 1.6.6), you are able to use just
(note that it is ‘test’ not ‘origin/test’) to perform magical DWIM-mery and create local branch ‘test’ for you, for which upstream would be remote-tracking branch ‘origin/test’.
The * (no branch)
in git branch
output means that you are on unnamed branch, in so called “detached HEAD” state (HEAD points directly to commit, and is not symbolic reference to some local branch). If you made some commits on this unnamed branch, you can always create local branch off current commit:
In this case, you probably want to create a local test
branch which is tracking the remote test
branch:
In earlier versions of git
, you needed an explicit --track
option, but that is the default now when you are branching off a remote branch.
How do I force an overwrite of local files on a git pull
?
The scenario is following:
This is the error I’m getting:
error: Untracked working tree file ‘public/images/icon.gif’ would be overwritten by merge
How do I force Git to overwrite them? The person is a designer - usually I resolve all the conflicts by hand, so the server has the most recent version that they just needs to update on their computer.
--hard
option, any local commits that haven’t been pushed will be lost.[*]
If you have any files that are not tracked by Git (e.g. uploaded user content), these files will not be affected.
I think this is the right way:
Then, you have two options:
OR If you are on some other branch:
git fetch
downloads the latest from remote without trying to merge or rebase anything.
Then the git reset
resets the master branch to what you just fetched. The --hard
option changes all the files in your working tree to match the files in origin/master
[*]: It’s worth noting that it is possible to maintain current local commits by creating a branch from master
before resetting:
git checkout master
git branch new-branch-to-save-current-commits
git fetch --all
git reset --hard origin/master
After this, all of the old commits will be kept in new-branch-to-save-current-commits
.
Uncommitted changes, however (even staged), will be lost. Make sure to stash and commit anything you need. For that you can run the following:
And then to reapply these uncommitted changes:
Try this:
It should do what you want.
WARNING: git clean
deletes all your untracked files/directories and can’t be undone.
Sometimes just clean -f
does not help. In case you have untracked DIRECTORIES, -d option also needed:
WARNING: git clean
deletes all your untracked files/directories and can’t be undone.
Consider using -n
(--dry-run
) flag first. This will show you what will be deleted without actually deleting anything:
Example output:
Would remove untracked-file-1.txt
Would remove untracked-file-2.txt
Would remove untracked/folder
...
I want to be able to do the following:
Create a local branch based on some other (remote or local) branch (via git branch
or git checkout -b
)
Push the local branch to the remote repository (publish), but make it trackable so git pull
and git push
will work immediately.
How do I do that?
I know about --set-upstream
in Git 1.7, but that is a post-creation action. I want to find a way to make a similar change when pushing the branch to the remote repository.
In Git 1.7.0 and later, you can checkout a new branch:
Edit files, add and commit. Then push with the -u
(short for --set-upstream
) option:
Git will set up the tracking information during the push.
If you are not sharing your repo with others, this is useful to push all your branches to the remote, and --set-upstream
tracking correctly for you:
(Not exactly what the OP was asking for, but this one-liner is pretty popular)
If you are sharing your repo with others this isn’t really good form as you will clog up the repo with all your dodgy experimental branches.
Prior to the introduction of git push -u
, there was no git push
option to obtain what you desire. You had to add new configuration statements.
If you create a new branch using:
You can use the git config
command to avoid editing directly the .git/config
file.
Or you can edit manually the .git/config
file to had tracking information to this branch.
Git clone will behave copying remote current working branch into local.
Is there any way to clone a specific branch by myself without switching branches on the remote repository?
The --single-branch
option is valid from version 1.7.10 and later.
Please see also the other answer which many people prefer.
You may also want to make sure you understand the difference. And the difference is: by invoking git clone --branch <branchname> url
you’re fetching all the branches and checking out one. That may, for instance, mean that your repository has a 5kB documentation or wiki branch and 5GB data branch. And whenever you want to edit your frontpage, you may end up cloning 5GB of data.
Again, that is not to say git clone --branch
is not the way to accomplish that, it’s just that it’s not always what you want to accomplish, when you’re asking about cloning a specific branch.
At the time of writing the original answer below, git had no --single-branch
option, but let’s preserve it for full satisfaction of angry bees.
The answer so badly disliked by copypasters was this:
Example:
With Git 1.7.10 and later, add --single-branch
to prevent fetching of all branches. Example, with OpenCV 2.4 branch:
Here is a really simple way to do it :)
Clone the repository
List all branches
Checkout the branch that you want
I mistakenly added files to git using the command:
I have not yet run git commit
. Is there a way to undo this, so these files won’t be included in the commit?
You can undo git add
before commit with
which will remove it from the current index (the “about to be committed” list) without changing anything else.
You can use
without any file name to unstage all due changes. This can come in handy when there are too many files to be listed one by one in a reasonable amount of time.
In old versions of Git, the above commands are equivalent to git reset HEAD <file>
and git reset HEAD
respectively, and will fail if HEAD
is undefined (because you haven’t yet made any commits in your repo) or ambiguous (because you created a branch called HEAD
, which is a stupid thing that you shouldn’t do). This was changed in Git 1.8.2, though, so in modern versions of Git you can use the commands above even prior to making your first commit:
“git reset” (without options or parameters) used to error out when you do not have any commits in your history, but it now gives you an empty index (to match non-existent commit you are not even on).
You want:
Reasoning:
When I was new to this, I first tried
(to undo my entire initial add), only to get this (not so) helpful message:
It turns out that this is because the HEAD ref (branch?) doesn’t exist until after the first commit. That is, you’ll run into the same beginner’s problem as me if your workflow, like mine, was something like:
git init
git add .
git status
… lots of crap scrolls by …
=> Damn, I didn’t want to add all of that.google “undo git add”
=> find Stack Overflow - yay
git reset .
It further turns out that there’s a bug logged against the unhelpfulness of this in the mailing list.
And that the correct solution was right there in the Git status output (which, yes, I glossed over as ’crap)
And the solution indeed is to use git rm --cached FILE
.
Note the warnings elsewhere here - git rm
deletes your local working copy of the file, but not if you use –cached. Here’s the result of git help rm
:
–cached Use this option to unstage and remove paths only from the index. Working tree files, whether modified or not, will be left.
I proceed to use
to remove everything and start again. Didn’t work though, because while add .
is recursive, turns out rm
needs -r
to recurse. Sigh.
Okay, now I’m back to where I started. Next time I’m going to use -n
to do a dry run and see what will be added:
I zipped up everything to a safe place before trusting git help rm
about the --cached
not destroying anything (and what if I misspelled it).
If you type:
git will tell you what is staged, etc, including instructions on how to unstage:
I find git does a pretty good job of nudging me to do the right thing in situations like this.
Note: Recent git versions (1.8.4.x) have changed this message:
How do I reset my local branch to be just like the branch on the remote repository?
I did:
But when I run a git status
,
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
modified: java/com/mycompany/TestContacts.java
modified: java/com/mycompany/TestParser.java
Can you please tell me why I have these ‘modified’? I haven’t touched these files? If I did, I want to remove those.
Setting your branch to exactly match the remote branch can be done in two steps:
If you want to save your current branch’s state before doing this (just in case), you can do:
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).
Note that the first example assumes that the remote repo’s name is “origin” and that the branch named “master” in the remote repo matches the currently checked-out branch in your local repo.
BTW, this situation that you’re in looks an awful lot like a common case where a push has been done into the currently checked out branch of a non-bare repository. Did you recently push into your local repo? If not, then no worries – something else must have caused these files to unexpectedly end up modified. Otherwise, you should be aware that it’s not recommended to push into a non-bare repository (and not into the currently checked-out branch, in particular).
I needed to do (the solution in the accepted answer):
Followed by:
To see what files will be removed (without actually removing them):
First, reset to the previously fetched HEAD
of the corresponding upstream branch:
The advantage of specifying @{u}
or its verbose form @{upstream}
is that the name of the remote repo and branch don’t have to be explicitly specified.
Next, as needed, remove untracked files, optionally also with -x
:
Finally, as needed, get the latest changes:
I know that Git tracks changes I make to my application, and it holds on to them until I commit the changes, but here’s where I’m hung up:
When I want to revert to a previous commit I use:
sh git reset --hard HEAD
And Git returns:
How do I then revert the files on my hard drive back to that previous commit?
My next steps were:
But none of the files have changed on my hard drive…
What am I doing right/wrong?
First, it’s always worth noting that git reset --hard
is a potentially dangerous command, since it throws away all your uncommitted changes. For safety, you should always check that the output of git status
is clean (that is, empty) before using it.
Initially you say the following:
So I know that Git tracks changes I make to my application, and it holds on to them until I commit the changes, but here’s where I’m hung up:
That’s incorrect. Git only records the state of the files when you stage them (with git add
) or when you create a commit. Once you’ve created a commit which has your project files in a particular state, they’re very safe, but until then Git’s not really “tracking changes” to your files. (for example, even if you do git add
to stage a new version of the file, that overwrites the previously staged version of that file in the staging area.)
In your question you then go on to ask the following:
When I want to revert to a previous commit I use: git reset –hard HEAD And git returns: HEAD is now at 820f417 micro
How do I then revert the files on my hard drive back to that previous commit?
If you do git reset --hard <SOME-COMMIT>
then Git will:
master
) back to point at <SOME-COMMIT>
.
<SOME-COMMIT>
.
HEAD
points to your current branch (or current commit), so all that git reset --hard HEAD
will do is to throw away any uncommitted changes you have.
So, suppose the good commit that you want to go back to is f414f31
. (You can find that via git log
or any history browser.) You then have a few different options depending on exactly what you want to do:
git reset --hard f414f31
. However, this is rewriting the history of your branch, so you should avoid it if you’ve shared this branch with anyone. Also, the commits you did after f414f31
will no longer be in the history of your master
branch.
Create a new commit that represents exactly the same state of the project as f414f31
, but just adds that on to the history, so you don’t lose any history. You can do that using the steps suggested in this answer - something like:
sh git reset --hard f414f31 git reset --soft HEAD@{1} git commit -m "Reverting to the state of the project at f414f31"
WARNING: git clean -f
will remove untracked files, meaning they’re gone for good since they aren’t stored in the repository. Make sure you really want to remove all untracked files before doing this.
Try this and see git clean -f
.
git reset --hard
will not remove untracked files, where as git-clean
will remove any files from the tracked root directory that are not under Git tracking.
Alternatively, as @Paul Betts said, you can do this (beware though - that removes all ignored files too)
git clean -df
git clean -xdf
CAUTION! This will also delete ignored files
Moderator Note: Given that this question has already had sixty-seven answers posted to it (some of them deleted), consider whether or not you are contributing anything new before posting another one.
What are the differences between git pull
and git fetch
?
In the simplest terms, git pull
does a git fetch
followed by a git merge
.
You can do a git fetch
at any time to update your remote-tracking branches under refs/remotes/<remote>/
.
This operation never changes any of your own local branches under refs/heads
, and is safe to do without changing your working copy. I have even heard of people running git fetch
periodically in a cron job in the background (although I wouldn’t recommend doing this).
A git pull
is what you would do to bring a local branch up-to-date with its remote version, while also updating your other remote-tracking branches.
Git documentation – git pull:
In its default mode,git pull
is shorthand forgit fetch
followed bygit merge FETCH_HEAD
.
When you use pull
, Git tries to automatically do your work for you. It is context sensitive, so Git will merge any pulled commits into the branch you are currently working in. pull
automatically merges the commits without letting you review them first. If you don’t closely manage your branches, you may run into frequent conflicts.
When you fetch
, Git gathers any commits from the target branch that do not exist in your current branch and stores them in your local repository. However, it does not merge them with your current branch. This is particularly useful if you need to keep your repository up to date, but are working on something that might break if you update your files. To integrate the commits into your master branch, you use merge
.
It is important to contrast the design philosophy of git with the philosophy of a more traditional source control tool like SVN.
Subversion was designed and built with a client/server model. There is a single repository that is the server, and several clients can fetch code from the server, work on it, then commit it back to the server. The assumption is that the client can always contact the server when it needs to perform an operation.
Git was designed to support a more distributed model with no need for a central repository (though you can certainly use one if you like). Also git was designed so that the client and the “server” don’t need to be online at the same time. Git was designed so that people on an unreliable link could exchange code via email, even. It is possible to work completely disconnected and burn a CD to exchange code via git.
In order to support this model git maintains a local repository with your code and also an additional local repository that mirrors the state of the remote repository. By keeping a copy of the remote repository locally, git can figure out the changes needed even when the remote repository is not reachable. Later when you need to send the changes to someone else, git can transfer them as a set of changes from a point in time known to the remote repository.
git fetch
is the command that says “bring my local copy of the remote repository up to date.”
git pull
says “bring the changes in the remote repository to where I keep my own code.”
Normally git pull
does this by doing a git fetch
to bring the local copy of the remote repository up to date, and then merging the changes into your own code repository and possibly your working copy.
The take away is to keep in mind that there are often at least three copies of a project on your workstation. One copy is your own repository with your own commit history. The second copy is your working copy where you are editing and building. The third copy is your local “cached” copy of a remote repository.
I don’t want to rename a remote branch, as described in Rename master branch for both local and remote Git repositories.
How can I rename a local branch which hasn’t been pushed to a remote branch?
In case you need to rename remote branch as well:
How do I rename both a Git local and remote branch name
If you want to rename a branch while pointed to any branch, do:
If you want to rename the current branch, you can do:
A way to remember this is -m
is for “move” (or mv
), which is how you rename files.
If you are on Windows or another case-insensitive filesystem, and there are any capitalization change in the name, you need to use -M
, otherwise, git will throw branch already exists error:
The above command will change your branch name, but you have to be very careful using the renamed branch, because it will still refer to the old upstream branch associated with it, if any.
If you want to push some changes into master after your local branch is renamed into new_branch_name (example name):
git push origin new_branch_name:master
(now changes will go to master branch but your local branch name is new_branch_name)
For more details, see “How to rename your local branch name in Git.”
To rename your current branch:
I pulled a project from GitHub a few days ago. I’ve since discovered that there are several forks on GitHub, and I neglected to note which one I took originally. How can I determine which of those forks I pulled?
If you want only the remote URL, or if your are not connected to a network that can reach the remote repo:
If you require full output and you are on a network that can reach the remote repo where the origin resides :
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.
Should you want this for scripting purposes, you can get only the URL with
You can try:
It will print all your remotes’ fetch/push URLs.
How do I resolve merge conflicts in Git?
Try: git mergetool
It opens a GUI that steps you through each conflict, and you get to choose how to merge. Sometimes it requires a bit of hand editing afterwards, but usually it’s enough by itself. It is much better than doing the whole thing by hand certainly.
As per @JoshGlover comment:
The command doesn’t necessarily open a GUI unless you install one. Running git mergetool
for me resulted in vimdiff
being used. You can install one of the following tools to use it instead: meld
, opendiff
, kdiff3
, tkdiff
, xxdiff
, tortoisemerge
, gvimdiff
, diffuse
, ecmerge
, p4merge
, araxis
, vimdiff
, emerge
.
Below is the sample procedure to use vimdiff
for resolve merge conflicts. Based on this link
Step 1: Run following commands in your terminal
git config merge.tool vimdiff
git config merge.conflictstyle diff3
git config mergetool.prompt false
This will set vimdiff as the default merge tool.
Step 2: Run following command in terminal
Step 3: You will see a vimdiff display in following format
╔═══════╦══════╦════════╗
║ ║ ║ ║
║ LOCAL ║ BASE ║ REMOTE ║
║ ║ ║ ║
╠═══════╩══════╩════════╣
║ ║
║ MERGED ║
║ ║
╚═══════════════════════╝
These 4 views are
LOCAL – this is file from the current branch
BASE – common ancestor, how file looked before both changes
REMOTE – file you are merging into your branch
MERGED – merge result, this is what gets saved in the repo
You can navigate among these views using ctrl+w. You can directly reach MERGED view using ctrl+w followed by j.
More info about vimdiff navigation here and here
Step 4. You could edit the MERGED view the following way
If you want to get changes from REMOTE
If you want to get changes from BASE
If you want to get changes from LOCAL
Step 5. Save, Exit, Commit and Clean up
:wqa
save and exit from vi
git commit -m "message"
git clean
Remove extra files (e.g. *.orig) created by diff tool.
Here’s a probable use-case, from the top:
You’re going to pull some changes, but oops, you’re not up to date:
git fetch origin
git pull origin master
From ssh://gitosis@example.com:22/projectname
* branch master -> FETCH_HEAD
Updating a030c3a..ee25213
error: Entry 'filename.c' not uptodate. Cannot merge.
So you get up-to-date and try again, but have a conflict:
git add filename.c
git commit -m "made some wild and crazy changes"
git pull origin master
From ssh://gitosis@example.com:22/projectname
* branch master -> FETCH_HEAD
Auto-merging filename.c
CONFLICT (content): Merge conflict in filename.c
Automatic merge failed; fix conflicts and then commit the result.
So you decide to take a look at the changes:
Oh my, oh my, upstream changed some things, but just to use my changes…no…their changes…
git checkout --ours filename.c
git checkout --theirs filename.c
git add filename.c
git commit -m "using theirs"
And then we try a final time
git pull origin master
From ssh://gitosis@example.com:22/projectname
* branch master -> FETCH_HEAD
Already up-to-date.
Ta-da!
I find merge tools rarely help me understand the conflict or the resolution. I’m usually more successful looking at the conflict markers in a text editor and using git log as a supplement.
Here are a few tips:
The best thing I have found is to use the “diff3” merge conflict style:
git config merge.conflictstyle diff3
This produces conflict markers like this:
<<<<<<<
Changes made on the branch that is being merged into. In most cases,
this is the branch that I have currently checked out (i.e. HEAD).
|||||||
The common ancestor version.
=======
Changes made on the branch that is being merged in. This is often a
feature/topic branch.
>>>>>>>
The middle section is what the common ancestor looked like. This is useful because you can compare it to the top and bottom versions to get a better sense of what was changed on each branch, which gives you a better idea for what the purpose of each change was.
If the conflict is only a few lines, this generally makes the conflict very obvious. (Knowing how to fix a conflict is very different; you need to be aware of what other people are working on. If you’re confused, it’s probably best to just call that person into your room so they can see what you’re looking at.)
If the conflict is longer, then I will cut and paste each of the three sections into three separate files, such as “mine”, “common” and “theirs”.
Then I can run the following commands to see the two diff hunks that caused the conflict:
This is not the same as using a merge tool, since a merge tool will include all of the non-conflicting diff hunks too. I find that to be distracting.
Somebody already mentioned this, but understanding the intention behind each diff hunk is generally very helpful for understanding where a conflict came from and how to handle it.
This shows all of the commits that touched that file in between the common ancestor and the two heads you are merging. (So it doesn’t include commits that already exist in both branches before merging.) This helps you ignore diff hunks that clearly are not a factor in your current conflict.
Verify your changes with automated tools.
If you have automated tests, run those. If you have a lint, run that. If it’s a buildable project, then build it before you commit, etc. In all cases, you need to do a bit of testing to make sure your changes didn’t break anything. (Heck, even a merge without conflicts can break working code.)
Plan ahead; communicate with co-workers.
Planning ahead and being aware of what others are working on can help prevent merge conflicts and/or help resolve them earlier – while the details are still fresh in mind.
For example, if you know that you and another person are both working on different refactoring that will both affect the same set of files, you should talk to each other ahead of time and get a better sense for what types of changes each of you is making. You might save considerable time and effort if you conduct your planned changes serially rather than in parallel.
For major refactorings that cut across a large swath of code, you should strongly consider working serially: everybody stops working on that area of the code while one person performs the complete refactoring.
If you can’t work serially (due to time pressure, maybe), then communicating about expected merge conflicts at least helps you solve the problems sooner while the details are still fresh in mind. For example, if a co-worker is making a disruptive series of commits over the course of a one-week period, you may choose to merge/rebase on that co-workers branch once or twice each day during that week. That way, if you do find merge/rebase conflicts, you can solve them more quickly than if you wait a few weeks to merge everything together in one big lump.
If you’re unsure of a merge, don’t force it.
Merging can feel overwhelming, especially when there are a lot of conflicting files and the conflict markers cover hundreds of lines. Often times when estimating software projects we don’t include enough time for overhead items like handling a gnarly merge, so it feels like a real drag to spend several hours dissecting each conflict.
In the long run, planning ahead and being aware of what others are working on are the best tools for anticipating merge conflicts and prepare yourself to resolve them correctly in less time.
I wrote the wrong thing in a commit message.
How can I change the message? The commit has not been pushed yet.
will open your editor, allowing you to change the commit message of the most recent commit. Additionally, you can set the commit message directly in the command line with:
…however, this can make multi-line commit messages or small corrections more cumbersome to enter.
Make sure you don’t have any working copy changes staged before doing this or they will get committed too. (Unstaged changes will not get committed.)
If you’ve already pushed your commit up to your remote branch, then you’ll need to force push the commit with:
Warning: force-pushing will overwrite the remote branch with the state of your local one. If there are commits on the remote branch that you don’t have in your local branch, you will lose those commits.
Warning: be cautious about amending commits that you have already shared with other people. Amending commits essentially rewrites them to have different SHA IDs, which poses a problem if other people have copies of the old commit that you’ve rewritten. Anyone who has a copy of the old commit will need to synchronize their work with your newly re-written commit, which can sometimes be difficult, so make sure you coordinate with others when attempting to rewrite shared commit history, or just avoid rewriting shared commits altogether.
Another option is to use interactive rebase.
This allows you to edit any message you want to update even if it’s not the latest message.
In order to do a git squash, follow these steps:
Once you squash your commits - choose the e/r
for editing the message
When you use the git rebase -i HEAD~X
there can be more than X
commits. Git will “collect” all the commits in the last X
commits and if there was a merge somewhere in between that range you will see all the commits as well so the outcome will be X+.
If you have to do it for more than a single branch and you might face conflicts when amending the content, set up git rerere
and let git resolve those conflicts automatically for you.
If the commit you want to fix isn’t the most recent one:
git rebase --interactive $parent_of_flawed_commit
An editor will come up, with a list of all commits since the one you gave.
pick
to reword
(or on old versions of Git, to edit
) in front of any commits you want to fix.
For each commit you want to reword, Git will drop you back into your editor. For each commit you want to edit, Git drops you into the shell. If you’re in the shell:
git commit --amend
git rebase --continue
Most of this sequence will be explained to you by the output of the various commands as you go. It’s very easy, you don’t need to memorise it – just remember that git rebase --interactive
lets you correct commits no matter how long ago they were.
Note that you will not want to change commits that you have already pushed. Or maybe you do, but in that case you will have to take great care to communicate with everyone who may have pulled your commits and done work on top of them. How do I recover/resynchronise after someone pushes a rebase or a reset to a published branch?
How do I discard changes in my working copy that are not in the index?
Another quicker way is:
You don’t need to include --include-untracked
if you don’t want to be thorough about it.
After that, you can drop that stash with a git stash drop
command if you like.
For all unstaged files in current working directory use:
For a specific file use:
--
here to remove argument ambiguation.
It seems like the complete solution is:
git clean
removes all untracked files (warning: while it won’t delete ignored files mentioned directly in .gitignore, it may delete ignored files residing in folders) and git checkout
clears all unstaged changes.
My colleague and I are working on the same repository we’ve branched it into two branches each technically for different projects, but they have similarities so we’ll sometimes want to commit back to the *master
from the branch
.
However, I have the branch
. My question is, how can my colleague pull that branch specifically?
A git clone
of the repo does not seem to create the branches locally for him, though I can see them live on unfuddle after a push on my end.
Also, when I originally made the branch I did -b checkout
. Not sure if that makes much difference?
$ git branch -r
origin/HEAD -> origin/master
origin/daves_branch
origin/discover
origin/master
$ git fetch origin discover
$ git checkout discover
These are the commands I ran. But it definitely is not working.
I want to be able to check out that branch and then push and commit back just the branches changes from various collaborators or workstations.
You need to create a local branch that tracks a remote branch. The following command will create a local branch named daves_branch, tracking the remote branch origin/daves_branch. When you push your changes the remote branch will be updated.
For most recent versions of git:
--track
is shorthand for git checkout -b [branch] [remotename]/[branch]
where [remotename] is origin in this case and [branch] is twice the same, daves_branch in this case.
For git 1.5.6.5 you needed this:
For git 1.7.2.3 and higher this is enough (might have started earlier but this is the earliest confirmation I could find quickly):
Note that with recent git versions, this command will not create a local branch and will put you in a ‘detached HEAD’ state. If you want a local branch, use the --track
option. Full details here: http://git-scm.com/book/en/v2/Git-Branching-Remote-Branches#Tracking-Branches
I have used fetch
followed by checkout
…
…where <rbranch>
is the remote branch or source ref and <lbranch>
is the as yet non-existent local branch or destination ref you want to track and which you probably want to name the same as the remote branch or source ref. This is explained under options in the explanation of <refspec>
.
Git is so smart it auto completes the first command if I tab after the first few letters of the remote branch. IE: I don’t even have to name the local branch, Git automatically copies the name of the remote branch for me. Thanks Git!
Also as the answer in this similar SO post shows, if you don’t name the local branch in fetch
, you can still create it when you check it out by using the -b
flag. IE: git fetch <remote> <branch>
followed by git checkout -b <branch> <remote>/<branch>
does exactly the same as my initial answer. And evidently if your repo has only one remote, then you can just do git checkout <branch>
after fetch
and it will create a local branch for you. EG: You just cloned a repo and want to check out additional branches from the remote.
I believe that some of the documentation for fetch
may have been copied verbatim from pull
. In particular the section on <refspec>
in options is the same. However, I do not believe that fetch
will ever merge
, so that if you leave the destination side of the colon empty fetch
should do nothing.
NOTE: That git fetch <remote> <refspec>
is short for git fetch <remote> <refspec>:
which would therefore do nothing, but git fetch <remote> <tag>
is the same as git fetch <remote> <tag>:<tag>
which should copy the remote <tag>
locally.
I guess this is only helpful if you want to copy a remote branch locally, but not necessarily check it out right away. Otherwise I now would use the accepted answer above, which is explained in detail in the first section of the checkout description and later in the options section under the explanation of --track
, since it’s a 1-liner. Well… sort of a 1-liner, because you would still have to run git fetch <remote>
first.
FYI: The order of the <refspecs>
(source:destination) explains the bizarre pre Git-1.7 method for deleting remote branches. IE: Push nothing into the destination refspec.
If you are trying to “checkout” a new remote branch (that exists only on the remote, but not locally), here’s what you’ll need:
This assumes you want to fetch from origin. If not, replace origin by your remote name.
How do you delete untracked local files from your current working tree?
As per the Git Documentation git clean
Remove untracked files from the working tree
Step 1 is to show what will be deleted by using the -n
option:
Clean Step - beware: this will delete files:
git clean -f -d
or git clean -fd
git clean -f -X
or git clean -fX
git clean -f -x
or git clean -fx
Note the case difference on the X
for the two latter commands.
If clean.requireForce
is set to “true” (the default) in your configuration, one needs to specify -f
otherwise nothing will actually happen.
Again see the git-clean
docs for more information.
-f
,--force
If the Git configuration variable clean.requireForce is not set to false, git clean will refuse to run unless given
-f
,-n
or-i
.
-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.
-n
,--dry-run
Don’t actually remove anything, just show what would be done.
-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.
Use git clean -f -d
to make sure that directories are also removed.
Don’t actually remove anything, just show what would be done.
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.
You can then check if your files are really gone with git status
.
I am surprised nobody mentioned this before:
That stands for interactive and you will get a quick overview of what is going to be deleted offering you the possibility to include/exclude the affected files. Overall, still faster than running the mandatory --dry-run
before the real cleaning.
You will have to toss in a -d
if you also want to take care of empty folders. At the end, it makes for a nice alias:
That being said, the extra hand holding of interactive commands can be tiring for experienced users. These days I just use the already mentioned git clean -fd
I would like to know how to delete a commit.
By delete
, I mean it is as if I didn’t make that commit, and when I do a push in the future, my changes will not push to the remote branch.
I read git help, and I think the command I should use is git reset --hard HEAD
. Is this correct?
Careful: git reset --hard
WILL DELETE YOUR WORKING DIRECTORY CHANGES. Be sure to stash any local changes you want to keep before running this command.
Assuming you are sitting on that commit, then this command will wack it…
The HEAD~1
means the commit before head.
Or, you could look at the output of git log
, find the commit id of the commit you want to back up to, and then do this:
If you already pushed it, you will need to do a force push to get rid of it…
However, if others may have pulled it, then you would be better off starting a new branch. Because when they pull, it will just merge it into their work, and you will get it pushed back up again.
If you already pushed, it may be better to use git revert
, to create a “mirror image” commit that will undo the changes. However, both commits will be in the log.
FYI – git reset --hard HEAD
is great if you want to get rid of WORK IN PROGRESS. It will reset you back to the most recent commit, and erase all the changes in your working tree and index.
Lastly, if you need to find a commit that you “deleted”, it is typically present in git reflog
unless you have garbage collected your repository.
If you have not yet pushed the commit anywhere, you can use git rebase -i
to remove that commit. First, find out how far back that commit is (approximately). Then do:
The ~N
means rebase the last N
commits (N
must be a number, for example HEAD~10
). Then, you can edit the file that Git presents to you to delete the offending commit. On saving that file, Git will then rewrite all the following commits as if the one you deleted didn’t exist.
The Git Book has a good section on rebasing with pictures and examples.
Be careful with this though, because if you change something that you have pushed elsewhere, another approach will be needed unless you are planning to do a force push.
Another possibility is one of my personal favorite commands:
This will start the rebase in interactive mode -i
at the point just before the commit you want to whack. The editor will start up listing all of the commits since then. Delete the line containing the commit you want to obliterate and save the file. Rebase will do the rest of the work, deleting only that commit, and replaying all of the others back into the log.
I have added a file named "file1.txt"
to a Git repository. After that, I committed it, added a couple of directories called dir1
and dir2
, and committed them to the Git repository.
Now the current repository has "file1.txt"
, dir1
, and dir2
. How can I delete "file1.txt"
without affecting others, like dir1
and dir2
?
Use git rm
:
But if you want to remove the file only from the Git repository and not remove it from the filesystem, use:
And to push changes to remote repo
git rm file.txt
removes the file from the repo but also deletes it from the local file system.
To remove the file from the repo and not delete it from the local file system use:
git rm --cached file.txt
The below exact situation is where I use git to maintain version control for my business’s website, but the “mickey” directory was a tmp folder to share private content with a CAD developer. When he needed HUGE files, I made a private, unlinked directory and ftpd the files there for him to fetch via browser. Forgetting I did this, I later performed a git add -A
from the website’s base directory. Subsequently, git status
showed the new files needing committing. Now I needed to delete them from git’s tracking and version control…
Sample output below is from what just happened to me, where I unintentionally deleted the .003
file. Thankfully, I don’t care what happened to the local copy to .003
, but some of the other currently changed files were updates I just made to the website and would be epic to have been deleted on the local file system! “Local file system” = the live website (not a great practice, but is reality).
[~/www]$ git rm shop/mickey/mtt_flange_SCN.7z.003
error: 'shop/mickey/mtt_flange_SCN.7z.003' has local modifications
(use --cached to keep the file, or -f to force removal)
[~/www]$ git rm -f shop/mickey/mtt_flange_SCN.7z.003
rm 'shop/mickey/mtt_flange_SCN.7z.003'
[~/www]$
[~/www]$ git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# deleted: shop/mickey/mtt_flange_SCN.7z.003
#
# Changed but not updated:
# (use "git add <file>..." to update what will be committed)
# (use "git checkout -- <file>..." to discard changes in working directory)
#
# modified: shop/mickey/mtt_flange_SCN.7z.001
# modified: shop/mickey/mtt_flange_SCN.7z.002
[~/www]$ ls shop/mickey/mtt_flange_S*
shop/mickey/mtt_flange_SCN.7z.001 shop/mickey/mtt_flange_SCN.7z.002
[~/www]$
[~/www]$
[~/www]$ git rm --cached shop/mickey/mtt_flange_SCN.7z.002
rm 'shop/mickey/mtt_flange_SCN.7z.002'
[~/www]$ ls shop/mickey/mtt_flange_S*
shop/mickey/mtt_flange_SCN.7z.001 shop/mickey/mtt_flange_SCN.7z.002
[~/www]$
[~/www]$
[~/www]$ git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# deleted: shop/mickey/mtt_flange_SCN.7z.002
# deleted: shop/mickey/mtt_flange_SCN.7z.003
#
# Changed but not updated:
# modified: shop/mickey/mtt_flange_SCN.7z.001
[~/www]$
Update: This answer is getting some traffic, so I thought I’d mention my other Git answer shares a couple of great resources: This page has a graphic that help demystify Git for me. The “Pro Git” book is online and helps me a lot.
First, if you are using git rm
, especially for multiple files, consider any wildcard will be resolved by the shell, not by the git
command.
But, if your file is already on GitHub, you can (since July 2013) directly delete it from the web GUI!
Simply view any file in your repository, click the trash can icon at the top, and commit the removal just like any other web-based edit.
Then “git pull
” on your local repo, and that will delete the file locally too.
Which makes this answer a (roundabout) way to delete a file from git repo?
(Not to mention that a file on GitHub is in a “git repo”)
(the commit will reflect the deletion of that file):
And just like that, it’s gone.
For help with these features, be sure to read our help articles on creating, moving, renaming, and deleting files.
Note: Since it’s a version control system, Git always has your back if you need to recover the file later.
The last sentence means that the deleted file is still part of the history, and you can restore it easily enough (but not yet through the GitHub web interface):
See “Restore a deleted file in a Git repo”.
I created a local branch which I want to ‘push’ upstream. There is a similar question here on Stack Overflow on how to track a newly created remote branch.
However, my workflow is slightly different. First I want to create a local branch, and I will only push it upstream when I’m satisfied and want to share my branch.
UPDATE With Git 2.0 there is a simpler answer I have written below: https://stackoverflow.com/a/27185855/109305
As of Git 2.0 the behaviour has become simpler:
You can configure git with push.default = current
to make life easier:
I added this so now I can just push a new branch upstream with
-u
will track remote branch of same name. Now with this configuration you will auto-guess the remote reference to git push. From git.config documentation:
push.default
Defines the action git push should take if no refspec is explicitly given.
push.default = current
- push the current branch to update a branch with the same name on the receiving end. Works in both central and non-central workflows.
For me, this is a good simplification of my day-to-day Git workflow. The configuration setting takes care of the ‘usual’ use case where you add a branch locally and want to create it remotely. Also, I can just as easily create local branches from remotes by just doing git co remote_branch_name
(as opposed to using --set-upstream-to
flag).
I know this question and the accepted answers are rather old, but the behaviour has changed so that now configuration options exists to make your workflow simpler.
To add to your global Git configuration, run this on the command line:
First, you create your branch locally:
The remote branch is automatically created when you push it to the remote server. So when you feel ready for it, you can just do:
Where <remote-name>
is typically origin
, the name which git gives to the remote you cloned from. Your colleagues would then just pull that branch, and it’s automatically created locally.
Note however that formally, the format is:
But when you omit one, it assumes both branch names are the same. Having said this, as a word of caution, do not make the critical mistake of specifying only :<remote-branch-name>
(with the colon), or the remote branch will be deleted!
So that a subsequent git pull
will know what to do, you might instead want to use:
As described below, the --set-upstream
option sets up an upstream branch:
For every branch that is up to date or successfully pushed, add upstream (tracking) reference, used by argument-less git-pull(1) and other commands.
First, you must create your branch locally
After that, you can work locally in your branch, when you are ready to share the branch, push it. The next command push the branch to the remote repository origin and tracks it
Teammates can reach your branch, by doing:
You can continue working in the branch and pushing whenever you want without passing arguments to git push (argumentless git push will push the master to remote master, your_branch local to remote your_branch, etc…)
Teammates can push to your branch by doing commits and then push explicitly
Or tracking the branch to avoid the arguments to git push
git checkout --track -b your_branch origin/your_branch
... work ...
git commit
... work ...
git commit
git push
Within my master branch, I did a git merge some-other-branch
locally, but never pushed the changes to origin master. I didn’t mean to merge, so I’d like to undo it. When doing a git status
after my merge, I was getting this message:
Based upon some instructions I found, I tried running
but now I’m getting this message with git status
:
I don’t want my branch to be ahead by any number of commits. How do I get back to that point?
With git reflog
check which commit is one prior the merge (git reflog
will be a better option than git log
). Then you can reset it using:
There’s also another way:
It will get you back 1 commit.
Be aware that any modified and uncommitted/unstashed files will be reset to their unmodified state. To keep them either stash changes away or see --merge
option below.
As @Velmont suggested below in his answer, in this direct case using:
might yield better results, as it should preserve your changes. ORIG_HEAD
will point to a commit directly before merge has occurred, so you don’t have to hunt for it yourself.
A further tip is to use the --merge
switch instead of --hard
since it doesn’t reset files unnecessarily:
–merge
Resets the index and updates the files in the working tree that are different between <commit> and HEAD, but keeps those which are different between the index and working tree (i.e. which have changes which have not been added).
Assuming your local master was not ahead of origin/master, you should be able to do
Then your local master
branch should look identical to origin/master
.
See chapter 4 in the Git book and the original post by Linus Torvalds.
To undo a merge that was already pushed:
Be sure to revert the revert if you’re committing the branch again, like Linus said.
I have made some changes to a file which has been committed a few times as part of a group of files, but now want to reset/revert the changes on it back to a previous version.
I have done a git log
along with a git diff
to find the revision I need, but just have no idea how to get the file back to its former state in the past.
Assuming the hash of the commit you want is c5f567
:
The git checkout man page gives more information.
If you want to revert to the commit before c5f567
, append ~1
(works with any number):
As a side note, I’ve always been uncomfortable with this command because it’s used for both ordinary things (changing between branches) and unusual, destructive things (discarding changes in the working directory).
You can quickly review the changes made to a file using the diff command:
Then to revert a specific file to that commit use the reset command:
You may need to use the --hard
option if you have local modifications.
A good workflow for managaging waypoints is to use tags to cleanly mark points in your timeline. I can’t quite understand your last sentence but what you may want is diverge a branch from a previous point in time. To do this, use the handy checkout command:
You can then rebase that against your mainline when you are ready to merge those changes:
You can use any reference to a git commit, including the SHA-1 if that’s most convenient. The point is that the command looks like this:
git checkout [commit-ref] -- [filename]
Executing the command git clone git@github.com:whatever
creates a directory in my current folder named whatever, and drops the contents of the Git repository into that folder:
My problem is that I need the contents of the Git repository cloned into my current directory so that they appear in the proper location for the web server:
I know how to move the files after I’ve cloned the repository, but this seems to break Git, and I’d like to be able to update just by calling git pull
. How can I do this?
Option A:
Ergo, for right here
use:
Option B:
Move the .git
folder, too. Note that the .git
folder is hidden in most graphical file explorers, so be sure to show hidden files.
The first line grabs all normal files, the second line grabs dot-files. It is also possibe to do it in one line by enabling dotglob (i.e. shopt -s dotglob
) but that is probably a bad solution if you are asking the question this answer answers.
Better yet:
Keep your working copy somewhere else, and create a symbolic link. Like this:
For you case this would be something like:
Which easily could be changed to test if you wanted it, i.e.:
without moving files around. Added -fn
in case someone is copying these lines (-f
is force, -n
avoid some often unwanted interactions with already and non-existing links).
If you just want it to work, use Option A, if someone else is going to look at what you have done, use Option C.
The example I think a lot of people asking this question are after is this. If you are in the directory you want the contents of the git repository dumped to, run:
The “.” at the end specifies the current folder as the checkout folder.
Go into the folder.. If the folder is empty, then:
else
I clone my repository with:
But after I change some files and add
and commit
them, I want to push them to the server:
But the error I get back is:
Maybe you just need to commit. I ran into this when I did:
Oops! Never committed!
All I had to do was:
Success!
Try git show-ref
to see what refs do you have. Is there refs/heads/master
?
You can try git push origin HEAD:master
as more local-reference-independent solution. This explicitly states that you want to push the local ref HEAD
to the remote ref master
(see the git-push refspec documentation).
I used git pull
and had a merge conflict:
I know that the other version of the file is good and that mine is bad so all my changes should be abandoned. How can I do this?
Since your pull
was unsuccessful then HEAD
(not HEAD^
) is the last “valid” commit on your branch:
The other piece you want is to let their changes over-ride your changes.
Older versions of git allowed you to use the “theirs” merge strategy:
But this has since been removed, as explained in this message by Junio Hamano (the Git maintainer). As noted in the link, instead you would do this:
If your git version is >= 1.6.1, you can use git reset --merge
.
Also, as @Michael Johnson mentions, if your git version is >= 1.7.4, you can also use git merge --abort
.
As always, make sure you have no uncommitted changes before you start a merge.
From the git merge man page
git merge --abort
is equivalent to git reset --merge
when MERGE_HEAD
is present.
MERGE_HEAD
is present when a merge is in progress.
Also, regarding uncommitted changes when starting a merge:
If you have changes you don’t want to commit before starting a merge, just git stash
them before the merge and git stash pop
after finishing the merge or aborting it.
The command git add [--all|-A]
appears to be identical to git add .
. Is this correct? If not, how do they differ?
This answer only applies to Git version 1.x. For Git version 2.x, see other answers.
Summary:
git add -A
stages all changes
git add .
stages new files and modifications, without deletions
git add -u
stages modifications and deletions, without new files
Detail:
git add -A
is equivalent to git add .; git add -u
.
The important point about git add .
is that it looks at the working tree and adds all those paths to the staged changes if they are either changed or are new and not ignored, it does not stage any ‘rm’ actions.
git add -u
looks at all the already tracked files and stages the changes to those files if they are different or if they have been removed. It does not add any new files, it only stages changes to already tracked files.
git add -A
is a handy shortcut for doing both of those.
You can test the differences out with something like this (note that for Git version 2.x your output for git add .
git status
will be different):
git init
echo Change me > change-me
echo Delete me > delete-me
git add change-me delete-me
git commit -m initial
echo OK >> change-me
rm delete-me
echo Add me > add-me
git status
# Changed but not updated:
# modified: change-me
# deleted: delete-me
# Untracked files:
# add-me
git add .
git status
# Changes to be committed:
# new file: add-me
# modified: change-me
# Changed but not updated:
# deleted: delete-me
git reset
git add -u
git status
# Changes to be committed:
# modified: change-me
# deleted: delete-me
# Untracked files:
# add-me
git reset
git add -A
git status
# Changes to be committed:
# new file: add-me
# modified: change-me
# deleted: delete-me
Here is a table for quick understanding:
Git Version 1.x:
Git Version 2.x:
Long-form flags:
git add -A
is equivalent to git add --all
git add -u
is equivalent to git add --update
Further reading:
With Git 2.0, git add -A
is default: git add .
equals git add -A .
.
git add <path>
is the same as “git add -A <path>
” now, so that “git add dir/
” will notice paths you removed from the directory and record the removal.
In older versions of Git, “git add <path>
” used to ignore removals.You can say “
git add --ignore-removal <path>
” to add only added or modified paths in<path>
, if you really want to.
git add
is like git add :/
(add everything from top git repo folder).
Note that git 2.7 (Nov. 2015) will allow you to add a folder named “:
”!
See commit 29abb33 (25 Oct 2015) by Junio C Hamano (gitster
).
Note that starting git 2.0 (Q1 or Q2 2014), when talking about git add .
(current path within the working tree), you must use ‘.
’ in the other git add
commands as well.
That means:
“git add -A .
” is equivalent to “git add .; git add -u .
”
(Note the extra ‘.
’ for git add -A
and git add -u
)
Because git add -A
or git add -u
would operate (starting git 2.0 only) on the entire working tree, and not just on the current path.
Those commands will operate on the entire tree in Git 2.0 for consistency with “
git commit -a
” and other commands. Because there will be no mechanism to make “git add -u
” behave as if “git add -u .
”, it is important for those who are used to “git add -u
” (without pathspec) updating the index only for paths in the current subdirectory to start training their fingers to explicitly say “git add -u .
” when they mean it before Git 2.0 comes.A warning is issued when these commands are run without a pathspec and when you have local changes outside the current directory, because the behaviour in Git 2.0 will be different from today’s version in such a situation.
How can I view the change history of an individual file in Git, complete details with what has changed?
I have got as far as:
which shows me the commit history of the file, but how do I get at the content of each of the file changes?
I’m trying to make the transition from MS SourceSafe and that used to be a simple right-click
→ show history
.
For this I’d use:
or to follow filename past renames
You can use
to let git generate the patches for each log entry.
See
for more options - it can actually do a lot of nice things :) To get just the diff for a specific commit you can
or any other revision by identifier. Or use
to browse the changes visually.
git log --follow -p -- path-to-file
This will show the entire history of the file (including history beyond renames and with diffs for each change).
In other words, if the file named bar
was once named foo
, then git log -p bar
(without the --follow
option) will only show the file’s history up to the point where it was renamed – it won’t show the file’s history when it was known as foo
. Using git log --follow -p bar
will show the file’s entire history, including any changes to the file when it was known as foo
. The -p
option ensures that diffs are included for each change.
How can I squash my last X commits together into one commit using Git?
Use git rebase -i <after-this-commit>
and replace “pick” on the second and subsequent commits with “squash” or “fixup”, as described in the manual.
In this example, <after-this-commit>
is either the SHA1 hash or the relative location from the HEAD of the current branch from which commits are analyzed for the rebase command. For example, if the user wishes to view 5 commits from the current HEAD in the past the command is git rebase -i HEAD~5
.
You can do this fairly easily without git rebase
or git merge --squash
. In this example, we’ll squash the last 3 commits.
If you want to write the new commit message from scratch, this suffices:
If you want to start editing the new commit message with a concatenation of the existing commit messages (i.e. similar to what a pick/squash/squash/…/squash git rebase -i
instruction list would start you with), then you need to extract those messages and pass them to git commit
:
Both of those methods squash the last three commits into a single new commit in the same way. The soft reset just re-points HEAD to the last commit that you do not want to squash. Neither the index nor the working tree are touched by the soft reset, leaving the index in the desired state for your new commit (i.e. it already has all the changes from the commits that you are about to “throw away”).
You can use git merge --squash
for this, which is slightly more elegant than git rebase -i
. Suppose you’re on master and you want to squash the last 12 commits into one.
WARNING: First make sure you commit your work—check that git status
is clean (since git reset --hard
will throw away staged and unstaged changes)
Then:
# Reset the current branch to the commit just before the last 12:
git reset --hard HEAD~12
# HEAD@{1} is where the branch was just before the previous command.
# This command sets the state of the index to be as it would just
# after a merge from that commit:
git merge --squash HEAD@{1}
# Commit those squashed changes. The commit message will be helpfully
# prepopulated with the commit messages of all the squashed commits:
git commit
The documentation for git merge
describes the --squash
option in more detail.
Update: the only real advantage of this method over the simpler git reset --soft HEAD~12 && git commit
suggested by Chris Johnsen in his answer is that you get the commit message prepopulated with every commit message that you’re squashing.
I have two branches, branch_1
and branch_2
.
I want to see the differences between the two branches in Git.
That will produce the diff between the tips of the two branches. If you’d prefer to find the diff from their common ancestor to test, you can use three dots instead of two:
A new branch from master
is created, we call it test
.
There are several developers who either commit to master
or create other branches and later merge into master
.
Let’s say work on test
is taking several days and you want to continuously keep test
updated with commits inside master
.
I would do git pull origin master
from test
.
Question 1: Is this the right approach? Other developers could have easily worked on same files as I have worked btw.
My work on test
is done and I am ready to merge it back to master
. Here are the two ways I can think of:
A:
git checkout test
git pull origin master
git push origin test
git checkout master
git pull origin test
B:
I am not using --rebase
because from my understanding, rebase will get the changes from master
and stack mine on top of that hence it could overwrite changes other people made.
Question 2: Which one of these two methods is right? What is the difference there?
The goal in all of this is to keep my test
branch updated with the things happening in master
and later I could merge them back into master
hoping to keep the timeline as linear as possible.
How I would do this
If I have a local branch from a remote one, I don’t feel comfortable with merging other branches than this one with the remote. Also I would not push my changes, until I’m happy with what I want to push and also I wouldn’t push things at all, that are only for me and my local repository. In your description it seems, that test
is only for you? So no reason to publish it.
git always tries to respect yours and others changes, and so will --rebase
. I don’t think I can explain it appropriately, so have a look at the Git book - Rebasing or git-ready: Intro into rebasing for a little description. It’s a quite cool feature
This is a very practical question, but all the answers above are not practical.
Like
This approach has two issues:
It’s unsafe, because we don’t know if there are any conflicts between test branch and master branch.
It would “squeeze” all test commits into one merge commit on master; that is to say on master branch, we can’t see the all change logs of test branch.
So, when we suspect there would some conflicts, we can have following git operations:
Test merge
before commit
, avoid a fast-forward commit by --no-ff
,
If conflict is encountered, we can run git status
to check details about the conflicts and try to solve
Once we solve the conflicts, or if there is no conflict, we commit
and push
them
But this way will lose the changes history logged in test branch, and it would make master branch to be hard for other developers to understand the history of the project.
So the best method is we have to use rebase
instead of merge
(suppose, when in this time, we have solved the branch conflicts).
Following is one simple sample, for advanced operations, please refer to http://git-scm.com/book/en/v2/Git-Branching-Rebasing
git checkout master
git pull
git checkout test
git pull
git rebase -i master
git checkout master
git merge test
Yep, when you have uppers done, all the Test branch’s commits will be moved onto the head of Master branch. The major benefit of rebasing is that you get a linear and much cleaner project history.
The only thing you need to avoid is: never use rebase
on public branch, like master branch.
Never do operations like the following:
Details for https://www.atlassian.com/git/tutorials/merging-vs-rebasing/the-golden-rule-of-rebasing
appendix:
Neither a rebase nor a merge should overwrite anyone’s changes (unless you choose to do so when resolving a conflict).
The usual approach while developing is
git checkout master
git pull
git checkout test
git log master.. # if you're curious
git merge origin/test # to update your local test from the fetch in the pull earlier
When you’re ready to merge back into master,
If you’re worried about breaking something on the merge, git merge --abort
is there for you.
Using push and then pull as a means of merging is silly. I’m also not sure why you’re pushing test to origin.
I have a repo (origin) on a USB key that I cloned on my hard drive (local). I moved “origin” to a NAS and successfully tested cloning it from here.
I would like to know if I can change the URI of “origin” in the settings of “local” so it will now pull from the NAS, and not from the USB key.
For now, I can see two solutions:
push everything to the usb-orign, and copy it to the NAS again (implies a lot of work due to new commits to nas-origin);
add a new remote to “local” and delete the old one (I fear I’ll break my history).
You can
(see git help remote
) or you can just edit .git/config
and change the URLs there. You’re not in any danger of losing history unless you do something very silly (and if you’re worried, just make a copy of your repo, since your repo is your history.)
git remote -v
# View existing remotes
# origin https://github.com/user/repo.git (fetch)
# origin https://github.com/user/repo.git (push)
git remote set-url origin https://github.com/user/repo2.git
# Change the 'origin' remote's URL
git remote -v
# Verify new remote URL
# origin https://github.com/user/repo2.git (fetch)
# origin https://github.com/user/repo2.git (push)
Change Host for a Git Origin Server
from: http://pseudofish.com/blog/2010/06/28/change-host-for-a-git-origin-server/
Hopefully this isn’t something you need to do. The server that I’ve been using to collaborate on a few git projects with had the domain name expire. This meant finding a way of migrating the local repositories to get back in sync.
Update: Thanks to @mawolf for pointing out there is an easy way with recent git versions (post Feb, 2010):
See the man page for details.
If you’re on an older version, then try this:
As a caveat, this works only as it is the same server, just with different names.
Assuming that the new hostname is newhost.com
, and the old one was oldhost.com
, the change is quite simple.
Edit the .git/config
file in your working directory. You should see something like:
[remote "origin"]
fetch = +refs/heads/*:refs/remotes/origin/*
url = ssh://oldhost.com/usr/local/gitroot/myproject.git
Change oldhost.com
to newhost.com
, save the file and you’re done.
From my limited testing (git pull origin; git push origin; gitx
) everything seems in order. And yes, I know it is bad form to mess with git internals.
I have a project in which I ran git init
. After several commits, I did git status
which told me everything was up to date and there were no local changes.
Then I made several consecutive changes and realized I wanted to throw everything away and get back to my original state. Will this command do it for me?
If you want to revert changes made to your working copy, do this:
If you want to revert changes made to the index (i.e., that you have added), do this. Warning this will reset all of your unpushed commits to master!:
If you want to revert a change that you have committed, do this:
If you want to remove untracked files (e.g., new files, generated files):
Or untracked directories (e.g., new or automatically generated directories):
Note: You may also want to run
as
will not remove untracked files, where as git-clean will remove any files from the tracked root directory that are not under git tracking. WARNING - BE CAREFUL WITH THIS! It is helpful to run a dry-run with git-clean first, to see what it will delete.
This is also especially useful when you get the error message
Which can occur when doing several things, one being updating a working copy when you and your friend have both added a new file of the same name, but he’s committed it into source control first, and you don’t care about deleting your untracked copy.
In this situation, doing a dry run will also help show you a list of files that would be overwritten.
.gitignore
(like build files)
.gitignore
Following are other commands I forget daily.
.gitignore
(like build files)
.gitignore
.gitignore
(like build files)
.gitignore
.gitignore
(like build files)
.gitignore
Test case for confirming all the above (use bash or sh):
mkdir project
cd project
git init
echo '*.built' > .gitignore
echo 'CODE' > a.sourceCode
mkdir b
echo 'CODE' > b/b.sourceCode
cp -r b c
git add .
git commit -m 'Initial checkin'
echo 'NEW FEATURE' >> a.sourceCode
cp a.sourceCode a.built
rm -rf c
echo 'CODE' > 'd.sourceCode'
See also
git revert
to make new commits that undo prior commits
git checkout
to go back in time to prior commits (may require running above commands first)
git stash
same as git reset
above, but you can undo it
I am looking for a simple git
command that provides a nicely formatted list of all files that were part of the commit given by a hash (SHA1), with no extraneous information.
I have tried:
Although it lists the files, it also includes unwanted diff information for each.
Is there another git
command that will provide just the list I want, so that I can avoid parsing it from the git show
output?
Preferred Way (because it’s a plumbing command; meant to be programmatic):
$ git diff-tree --no-commit-id --name-only -r bd61ad98
index.html
javascript/application.js
javascript/ie6.js
Another Way (less preferred for scripts, because it’s a porcelain command; meant to be user-facing)
--no-commit-id
suppresses the commit ID output.
--pretty
argument specifies an empty format string to avoid the cruft at the beginning.
--name-only
argument shows only the file names that were affected (Thanks Hank). Use --name-status
instead, if you want to see what happened to each file (Deleted, Modified, Added)
-r
argument is to recurse into sub-trees
If you want to get list of changed files:
If you want to get list of all files in a commit, you can use
I’ll just assume that gitk
is not desired for this. In that case, try git show --name-only <sha>
.
I’m trying to figure out how I can download a particular tag of a Git repository - it’s one version behind the current version.
I saw there was a tag for the previous version on the git web page, with object name of something long hex number.
But the version name is “Tagged release 1.1.5
” according the site.
I tried a command like this (with names changed):
And I did get something - a directory, a bunch of subdirectories, etc.
If it’s the whole repository, how do I get at the version I’m seeking? If not, how do I download that particular version?
will give you the whole repository.
After the clone, you can list the tags with $ git tag -l
and then checkout a specific tag:
Even better, checkout and create a branch (otherwise you will be on a branch named after the revision number of tag):
Will clone the repo and leave you on the tag you are interested in.
Documentation for 1.8.0 of git clone states.
–branch can also take tags and detaches the HEAD at that commit in the resulting repository.
For checking out only a given tag for deployment, I use e.g.:
This seems to be the fastest way to check out code from a remote repository if one has only interest in the most recent code instead of in a complete repository. In this way, it resembles the ‘svn co’ command.
Note: Per the Git manual, passing the --depth
flag implies --single-branch
by default.
–depth
Create a shallow clone with a history truncated to the specified number of commits. Implies –single-branch unless –no-single-branch is given to fetch the histories near the tips of all branches. If you want to clone submodules shallowly, also pass –shallow-submodules.
I’m from a Subversion background and, when I had a branch, I knew what I was working on with “These working files point to this branch”.
But with Git I’m not sure when I am editing a file in NetBeans or Notepad++, whether it’s tied to the master or another branch.
There’s no problem with git
in bash, it tells me what I’m doing.
should show all the local branches of your repo. The starred branch is your current branch.
If you want to retrieve only the name of the branch you are on, you can do:
To display the current branch you’re on, without the other branches listed, you can do the following:
Reference:
You have also git symbolic-ref HEAD
which displays the full refspec.
To show only the branch name in Git v1.8 and later (thank’s to Greg for pointing that out):
On Git v1.7+ you can also do:
Both should give the same branch name if you’re on a branch. If you’re on a detached head answers differ.
Note:
On an earlier client, this seems to work:
– Darien 26. Mar 2014
I know how to make a new branch that tracks remote branches, but how do I make an existing branch track a remote branch?
I know I can just edit the .git/config
file, but it seems there should be an easier way.
Given a branch foo
and a remote upstream
:
As of Git 1.8.0:
Or, if local branch foo
is not the current branch:
Or, if you like to type longer commands, these are equivalent to the above two:
As of Git 1.7.0:
Notes:
foo
to track remote branch foo
from remote upstream
.
git fetch upstream
beforehand.
You can do the following (assuming you are checked out on master and want to push to a remote branch master):
Set up the ‘remote’ if you don’t have it already
Now configure master to know to track:
And push:
I do this as a side-effect of pushing with the -u
option as in
The equivalent long option is --set-upstream
.
The git-branch
command also understands --set-upstream
, but its use can be confusing. Version 1.8.0 modifies the interface.
git branch --set-upstream
is deprecated and may be removed in a relatively distant future.git branch [-u|--set-upstream-to]
has been introduced with a saner order of arguments.…
It was tempting to saygit branch --set-upstream origin/master
, but that tells Git to arrange the local branch “origin/master” to integrate with the currently checked out branch, which is highly unlikely what the user meant. The option is deprecated; use the new--set-upstream-to
(with a short-and-sweet-u
) option instead.
Say you have a local foo
branch and want it to treat the branch by the same name as its upstream. Make this happen with
or just
I was doing some work in my repository and noticed a file had local changes. I didn’t want them anymore so I deleted the file, thinking I can just checkout a fresh copy. I wanted to do the Git equivalent of
Using git pull
didn’t seem to work. Some random searching led me to a site where someone recommended doing
(src
is the directory containing the deleted file).
Now I find out I have a detached head. I have no idea what that is. How can I undo?
Detached head means you are no longer on a branch, you have checked out a single commit in the history (in this case the commit previous to HEAD, i.e. HEAD^).
You only need to checkout the branch you were on, e.g.
Next time you have changed a file and want to restore it to the state it is in the index, don’t delete the file first, just do
This will restore the file foo to the state it is in the index.
git log -n 1
; this will display the most recent commit on the detached HEAD. Copy the commit hash.
git checkout master
git branch tmp <commit-hash>
. This will save your changes in a new branch called tmp
.
master
, run git merge tmp
from the master
branch. You should be on the master
branch after running git checkout master
.
If you have changed files you don’t want to lose, you can push them. I have committed them in the detached mode and after that you can move to a temporary branch to integrate later in master.
Extracted from:
A solution without creating a temporary branch.
How to exit (“fix”) detached HEAD state when you already changed something in this mode and, optionally, want to save your changes:
Commit changes you want to keep. If you want to take over any of the changes you made in detached HEAD state, commit them. Like:
sh git commit -a -m "your commit message"
Discard changes you do not want to keep. The hard reset will discard any uncommitted changes that you made in detached HEAD state:
(Without this, step 3 would fail, complaining about modified uncommitted files in the detached HEAD.)Check out your branch. Exit detached HEAD state by checking out the branch you worked on before, for example:
sh git checkout master
Take over your commits. You can now take over the commits you made in detached HEAD state by cherry-picking, as shown in my answer to another question.
sh git reflog git cherry-pick <hash1> <hash2> <hash3> …
I cloned a Git repository, which contains about five branches. However, when I do git branch
I only see one of them:
I know that I can do git branch -a
to see all the branches, but how would I pull all the branches locally so when I do git branch
, it shows the following?
You can fetch all branches from all remotes like this:
It’s basically a power move.
fetch
updates local copies of remote branches so this is always safe for your local branches BUT:
fetch
will not update local branches (which track remote branches); if you want to update your local branches you still need to pull every branch.
fetch
will not create local branches (which track remote branches), you have to do this manually. If you want to list all remote branches: git branch -a
To update local branches which track remote branches:
However, this can be still insufficient. It will work only for your local branches which track remote branches. To track all remote branches execute this oneliner BEFORE git pull --all
:
(It seems that pull fetches all branches from all remotes, but I always fetch first just to be sure.)
Run the first command only if there are remote branches on the server that aren’t tracked by your local branches.
P.S. AFAIK git fetch --all
and git remote update
are equivalent.
Kamil Szot’s comment, which folks have found useful.
I had to use:
because your code created local branches named
origin/branchname
and I was getting "refname ‘origin/branchname’ is ambiguous whenever I referred to it.
To list remote branches:
git branch -r
You can check them out as local branches with:
git checkout -b LocalName origin/remotebranchname
You will need to create local branches tracking remote branches.
Assuming that you’ve got only one remote called origin
, this snippet will create local branches for all remote tracking ones:
After that, git fetch --all
will update all local copies of remote branches.
Also, git pull --all
will update your local tracking branches, but depending on your local commits and how the ‘merge’ configure option is set it might create a merge commit, fast-forward or fail.
I’ve set up a remote non-bare “main” repo and cloned it to my computer. I made some local changes, updated my local repository, and pushed the changes back to my remote repo. Things were fine up to that point.
Now, I had to change something in the remote repo. Then I changed something in my local repo. I realized that the change to the remote repo was not needed. So I tried to git push
from my local repo to my remote repo, but I got an error like:
To prevent you from losing history, non-fast-forward updates were rejected Merge the remote changes before pushing again. See the ‘Note about fast-forwards’ section of
git push --help
for details.
I thought that probably a
would force my local copy to push changes to the remote one and make it the same. It does force the update, but when I go back to the remote repo and make a commit, I notice that the files contain outdated changes (ones that the main remote repo previously had).
As I mentioned in the comments to one of the answers:
[I] tried forcing, but when going back to master server to save the changes, i get outdated staging. Thus, when i commit the repositories are not the same. And when i try to use git push again, i get the same error.
How can I fix this issue?
Just do:
or if you have a specific repo:
This will delete your previous commit(s) and push your current one.
It may not be proper, but if anyone stumbles upon this page, thought they might want a simple solution…
Also note that -f
is short for --force
, so
will also work.
And if push --force
doesn’t work you can do push --delete
. Look at 2nd line on this instance:
git reset --hard HEAD~3 # reset current branch to 3 commits ago
git push origin master --delete # do a very very bad bad thing
git push origin master # regular push
But beware…
In other words:
force
push on a public repository.
pull
.
reset
or rewrite
history in a repo someone might have already pulled.
Of course there are exceptionally rare exceptions even to this rule, but in most cases it’s not needed to do it and it will generate problems to everyone else.
And always be careful with what you push to a public repo. Reverting:
git revert -n HEAD~3..HEAD # prepare a new commit reverting last 3 commits
git commit -m "sorry - revert last 3 commits because I was not careful"
git push origin master # regular push
In effect, both origin HEADs (from the revert and from the evil reset) will contain the same files.
push --force
Another problem push --force
may bring is when someone push anything before you do, but after you’ve already fetched. If you push force your rebased version now you will replace work from others.
git push --force-with-lease
introduced in the git 1.8.5 (thanks to @VonC comment on the question) tries to address this specific issue. Basically, it will bring an error and not push if the remote was modified since your latest fetch.
This is good if you’re really sure a push --force
is needed, but still want to prevent more problems. I’d go as far to say it should be the default push --force
behaviour. But it’s still far from being an excuse to force a push
. People who fetched before your rebase will still have lots of troubles, which could be easily avoided if you had reverted instead.
And since we’re talking about git --push
instances…
@linquize brought a good push force example on the comments: sensitive data. You’ve wrongly leaked data that shouldn’t be pushed. If you’re fast enough, you can “fix”*
it by forcing a push on top.
*
The data will still be on the remote unless you also do a garbage collect, or clean it somehow. There is also the obvious potential for it to be spread by others who’d fetched it already, but you get the idea.
First of all, I would not make any changes directly in the “main” repo. If you really want to have a “main” repo, then you should only push to it, never change it directly.
Regarding the error you are getting, have you tried git pull
from your local repo, and then git push
to the main repo? What you are currently doing (if I understood it well) is forcing the push and then losing your changes in the “main” repo. You should merge the changes locally first.
I have a master
and a development
branch, both pushed to GitHub. I’ve clone
d, pull
ed, and fetch
ed, but I remain unable to get anything other than the master
branch back.
I’m sure I’m missing something obvious, but I have read the manual and I’m getting no joy at all.
First, clone a remote Git repository and cd into it:
Next, look at the local branches in your repository:
But there are other branches hiding in your repository! You can see these using the -a
flag:
$ git branch -a
* master
remotes/origin/HEAD
remotes/origin/master
remotes/origin/v1.0-stable
remotes/origin/experimental
If you just want to take a quick peek at an upstream branch, you can check it out directly:
But if you want to work on that branch, you’ll need to create a local tracking branch which is done automatically by:
and you will see
Branch experimental set up to track remote branch experimental from origin.
Switched to a new branch 'experimental'
That last line throws some people: “New branch” - huh? What it really means is that the branch is taken from the index and created locally for you. The previous line is actually more informative as it tells you that the branch is being set up to track the remote branch, which usually means the origin/branch_name branch
Now, if you look at your local branches, this is what you’ll see:
You can actually track more than one remote repository using git remote
.
$ git remote add win32 git://example.com/users/joe/myproject-win32-port
$ git branch -a
* master
remotes/origin/HEAD
remotes/origin/master
remotes/origin/v1.0-stable
remotes/origin/experimental
remotes/win32/master
remotes/win32/new-widgets
At this point, things are getting pretty crazy, so run gitk
to see what’s going on:
If you have many remote branches that you want to fetch at once, do:
Now you can checkout any branch as you need to, without hitting the remote repository.
This Bash script helped me out:
#!/bin/bash
for branch in $(git branch --all | grep '^\s*remotes' | egrep --invert-match '(:?HEAD|master)$'); do
git branch --track "${branch##*/}" "$branch"
done
It will create tracking branches for all remote branches, except master (which you probably got from the original clone command). I think you might still need to do a
to be sure.
One liner:
Credits for one-liner go to user cfigit branch -a | grep -v HEAD | perl -ne 'chomp($_); s|^\*?\s*||; if (m|(.+)/(.+)| && not $d{$2}) {print qq(git branch --track $2 $1/$2\n)} else {$d{$_}=1}' | csh -xfs
As usual: test in your setup before copying rm -rf universe as we know it
I am using Git and I have committed few files using
Later, I found that a file had mistakenly been added to the commit.
How can I remove a file from the last commit?
I think other answers here are wrong, because this is a question of moving the mistakenly committed files back to the staging area from the previous commit, without cancelling the changes done to them. This can be done like Paritosh Singh suggested:
or
Then reset the unwanted files in order to leave them out from the commit:
Now commit again, you can even re-use the same commit message:
ATTENTION! If you only want to remove a file from your previous commit, and keep it on disk, read juzzlin’s answer just above.
If this is your last commit and you want to completely delete the file from your local and the remote repository, you can:
git rm <file>
git commit --amend
The amend flag tells git to commit again, but “merge” (not in the sense of merging two branches) this commit with the last commit.
As stated in the comments, using git rm
here is like using the rm
command itself!
Existing answers are all talking about removing the unwanted files from the last commit.
If you want to remove unwanted files from an old commit (even pushed) and don’t want to create a new commit, which is unnecessary, because of the action:
Find the commit that you want the file to conform to.
you can do this multiple times if you want to remove many files.
Find the commit_id of the commit on which the files were added mistakenly, let’s say “35c23c2” here
This command opens the editor according to your settings. The default one is vim.
Move the last commit, which should be “remove unwanted files”, to the next line of the incorrect commit(“35c23c2” in our case), and set the command as fixup
:
You should be good after saving the file.
To finish :
If you unfortunately get conflicts, you have to solve them manually.
I know how to provide a username and password to an HTTPS request like this:
But I’d like to know how to provide a username and password to the remote like this:
I’ve tried like this:
git clone username:password@git@remote.git
git clone git@username:password@remote.git
git clone git@remote.git@username:password
But they haven’t worked.
Use:
This way worked for me from a GitHub repository.
Based on Michael Scharf’s comment:
You can leave out the password so that it won’t be logged in your Bash history file:
It will prompt you for your password.
The user@host:path/to/repo
format tells Git to use ssh to log in to host
with username user
. From git help clone
:
An alternative scp-like syntax may also be used with the ssh protocol:
[user@]host.xz:path/to/repo.git/
The part before the @
is the username, and the authentication method (password, public key, etc.) is determined by ssh, not Git. Git has no way to pass a password to ssh, because ssh might not even use a password depending on the configuration of the remote server.
ssh-agent
to avoid typing passwords all the time
If you don’t want to type your ssh password all the time, the typical solution is to generate a public/private key pair, put the public key in your ~/.ssh/authorized_keys
file on the remote server, and load your private key into ssh-agent
. Also see Configuring Git over SSH to login once, GitHub’s help page on ssh key passphrases, gitolite’s ssh documentation, and Heroku’s ssh keys documentation.
If you have multiple accounts at a place like GitHub or Heroku, you’ll have multiple ssh keys (at least one per account). To pick which account you want to log in as, you have to tell ssh which private key to use.
For example, suppose you had two GitHub accounts: foo
and bar
. Your ssh key for foo
is ~/.ssh/foo_github_id
and your ssh key for bar
is ~/.ssh/bar_github_id
. You want to access git@github.com:foo/foo.git
with your foo
account and git@github.com:bar/bar.git
with your bar
account. You would add the following to your ~/.ssh/config
:
Host gh-foo
Hostname github.com
User git
IdentityFile ~/.ssh/foo_github_id
Host gh-bar
Hostname github.com
User git
IdentityFile ~/.ssh/bar_github_id
You would then clone the two repositories as follows:
git clone gh-foo:foo/foo.git # logs in with account foo
git clone gh-bar:bar/bar.git # logs in with account bar
Some services provide HTTP access as an alternative to ssh:
GitHub:
sh https://username:password@github.com/username/repository.git
Gitorious:
sh https://username:password@gitorious.org/project/repository.git
Heroku: See this support article.
WARNING: Adding your password to the clone URL will cause Git to store your plaintext password in .git/config
. To securely store your password when using HTTP, use a credential helper. For example:
git config --global credential.helper cache
git config --global credential.https://github.com.username foo
git clone https://github.com/foo/repository.git
The above will cause Git to ask for your password once every 15 minutes (by default). See git help credentials
for details.
In the comments of @Bassetassen’s answer, @plosco mentioned that you can use git clone https://<token>@github.com/username/repository.git
to clone from GitHub at the very least. I thought I would expand on how to do that, in case anyone comes across this answer like I did while trying to automate some cloning.
GitHub has a very handy guide on how to do this, but it doesn’t cover what to do if you want to include it all in one line for automation purposes. It warns that adding the token to the clone URL will store it in plaintext in .git/config
. This is obviously a security risk for almost every use case, but since I plan on deleting the repo and revoking the token when I’m done, I don’t care.
GitHub has a whole guide here on how to get a token, but here’s the TL;DR.
Same as the command @plosco gave, git clone https://<token>@github.com/<username>/<repository>.git
, just replace <token>
, <username>
and <repository>
with whatever your info is.
If you want to clone it to a specific folder, just insert the folder address at the end like so: git clone https://<token>@github.com/<username>/<repository.git> <folder>
, where <folder>
is, you guessed it, the folder to clone it to! You can of course use .
, ..
, ~
, etc. here like you can elsewhere.
Not all of this may be necessary, depending on how sensitive what you’re doing is.
rm -rf <folder>
.
git remote remove origin
or just remove the token by running git remote set-url origin https://github.com/<username>/<repository.git>
.
Note that I’m no pro, so the above may not be secure in the sense that no trace would be left for any sort of forensic work.
I have 2 directories on my GitHub repository. I’d like to delete one of them. How could I do that without deleting and re-creating entire repository?
You could checkout ‘master’ with both directories;
git rm -r one-of-the-directories
git commit -m "Remove duplicated directory"
git push origin <your-git-branch> (typically 'master', but not always)
As mentioned in the comments, what you usually want to do is remove this directory from git but not delete it entirely from the filesystem (local)
In that case use:
Steps to remove directory
Steps to ignore that folder in next commits
To ignore that folder from next commits make one file in root named .gitignore and put that folders name into it. You can put as many as you want
.gitignore file will be look like this
If, for some reason, what karmakaze said doesn’t work, you could try deleting the directory you want using or with your file system browser (ex. In Windows File Explorer). After deleting the directory, issuing the command:
git add -A
and then
git commit -m 'deleting directory'
and then
git push origin master
.
There is a file that was being tracked by git
, but now the file is on the .gitignore
list.
However, that file keeps showing up in git status
after it’s edited. How do you force git
to completely forget about it?
.gitignore
will prevent untracked files from being added (without an add -f
) to the set of files tracked by git, however git will continue to track any files that are already being tracked.
To stop tracking a file you need to remove it from the index. This can be achieved with this command.
If you want to remove a whole folder, you need to remove all files in it recursively.
The removal of the file from the head revision will happen on the next commit.
WARNING: While this will not remove the physical file from your local, it will remove the files from other developers machines on next git pull
.
The series of commands below will remove all of the items from the Git Index (not from the working directory or local repo), and then updates the Git Index, while respecting git ignores. PS. Index = Cache
First:
Then:
git update-index does the job for me:
Note: This solution is actually independent on .gitignore
as gitignore is only for untracked files.
edit: Since this answer was posted, a new option has been created and that should be prefered. You should use --skip-worktree
which is for modified tracked files that the user don’t want to commit anymore and keep --assume-unchanged
for performance to prevent git to check status of big tracked files. See https://stackoverflow.com/a/13631525/717372 for more details…
I have a project with multiple branches. I’ve been pushing them to GitHub, and now that someone else is working on the project I need to pull their branches from GitHub. It works fine in master. But say that someone created a branch xyz
. How can I pull branch xyz
from GitHub and merge it into branch xyz
on my localhost
?
I actually have my answer here: Push and pull branches in Git
But I get an error “! [rejected]” and something about “non fast forward”.
Any suggestions?
But I get an error “! [rejected]” and something about “non fast forward”
That’s because Git can’t merge the changes from the branches into your current master. Let’s say you’ve checked out branch master
, and you want to merge in the remote branch other-branch
. When you do this:
Git is basically doing this:
That is, a pull
is just a fetch
followed by a merge
. However, when pull
-ing, Git will only merge other-branch
if it can perform a fast-forward merge. A fast-forward merge is a merge in which the head of the branch you are trying to merge into is a direct descendent of the head of the branch you want to merge. For example, if you have this history tree, then merging other-branch
would result in a fast-forward merge:
However, this would not be a fast-forward merge:
To solve your problem, first fetch the remote branch:
Then merge it into your current branch (I’ll assume that’s master
), and fix any merge conflicts:
Simply track your remote branches explicitly and a simple git pull
will do just what you want:
The latter is a local operation.
Or even more fitting in with the GitHub documentation on forking:
You could pull a branch to a branch with the following commands.
When you are on the master branch you also could first checkout a branch like:
This creates a new branch, “xyz”, from the master and directly checks it out.
Then you do:
This pulls the new branch to your local xyz
branch.
I created a git repository with git init
. I’d like to delete it entirely and init a new one.
Git keeps all of its files in the .git
directory. Just remove that one and init again.
If you can’t find it, it’s because it is hidden.
In Windows 7, you need to go to your folder, click on Organize on the top left, then click on Folder and search options, then click on the View tab and click on the Show hidden files, folders and drives radio button.
On a Mac OS:
Open a Terminal (via Spotlight: press CMD + SPACE, type terminal
and press Enter) and run:
Note: The keyboard shortcut to show hidden files in Finder is CMD + SHIFT + . so it is no longer necessary to modify the finder config this way
You could also type cd
(the space is important), drag and drop your git repo folder from Finder to the terminal window, press return, then type rm -fr .git
, then return again.
On Ubuntu, use shortcut Ctrl + H.
If you really want to remove all of the repository, leaving only the working directory then it should be as simple as this.
The usual provisos about rm -rf
apply. Make sure you have an up to date backup and are absolutely sure that you’re in the right place before running the command. etc., etc.
If you want to delete all .git folders in a project use the following command:
This will also delete all the .git folders and .gitignore files from all subfolders
Lets say we have the following situation in git:
A created repository:
sh mkdir GitTest2 cd GitTest2 git init
Some modifications in the master take place and get committed.
sh echo "On Master" > file git commit -a -m "Initial commit"
Feature1 branched off master and some work is done:
sh git branch feature1 git checkout feature1 echo "Feature1" > featureFile git commit -a -m "Commit for feature1"
Meanwhile, a bug is discovered in the master-code and a hotfix-branch is established
sh git checkout master git branch hotfix1 git checkout hotfix1
The bug is fixed in the hotfix branch and merged back into the master (perhaps after a pull request/code review):
sh echo "Bugfix" > bugfixFile git commit -a -m "Bugfix Commit" git checkout master git merge --no-ff hotfix1
Development on feature1 continues:
sh git checkout feature1
Now my question: Say I need the hotfix in my feature branch, maybe because the bug also occurs there. How can I achieve this without duplicating the commits into my feature branch? I want to prevent to get two new commits on my feature branch which have no relation to the feature implementation. This especially seems important for me if I use Pull Requests: All these commits will also be included in the Pull Request and have to be reviewed although this has already been done (as the hotfix is already in the master).
I can not do a git merge master --ff-only
: “fatal: Not possible to fast-forward, aborting.”, but I am not sure if this helped me.
You should be able to rebase your branch on master:
Manage all conflicts that arise. When you get to the commits with the bugfixes (already in master), git will say that there were no changes and that maybe they were already applied. You then continue the rebase (while skipping the commits already in master) with
If you perform a git log
on your feature branch, you’ll see the bugfix commit appear only once, and in the master portion.
For a more detailed discussion, take a look at the Git book docs on git rebase
(https://git-scm.com/docs/git-rebase) which cover this exact use case.
================ Edit for additional context ====================
This answer was provided specifically for the question asked by @theomega, taking his particular situation into account. Note this part:
I want to prevent […] commits on my feature branch which have no relation to the feature implementation.
Rebasing his private branch on master is exactly what will yield that result. In contrast, merging master into his branch would precisely do what he specifically does not want to happen: adding a commit that is not related to the feature implementation he is working on via his branch.
To address the users that read the question title, skip over the actual content and context of the question, and then only read the top answer blindly assuming it will always apply to their (different) use case, allow me to elaborate:
git merge master
as in @Sven’s answer).
Finally, if you’re unhappy with the fact that this answer is not the best fit for your situation even though it was for @theomega, adding a comment below won’t be particularly helpful: I don’t control which answer is selected, only @theomega does.
How to merge the master branch into the feature branch? Easy:
There is no point in forcing a fast forward merge here, as it cannot be done. You committed both into the feature branch and the master branch. Fast forward is impossible now.
Have a look at gitflow. It is a branching model for git that can be followed, and you unconsciously already did. It also is an extension to git which adds some commands for the new workflow steps that do things automatically which you would otherwise need to do manually.
So what did you do right in your workflow? You have two branches to work with, your feature1 branch is basically the “develop” branch in the gitflow model.
You created a hotfix branch from master and merged it back. And now you are stuck.
The gitflow model asks you to merge the hotfix also to the devel branch, which is “feature1” in your case.
So the real answer would be:
This adds all the changes that were made inside the hotfix to the feature branch, but ONLY those changes. They might conflict with other development changes in the branch, but they will not conflict with the master branch should you merge the feature branch back to master eventually.
Be very careful with rebasing. Only rebase if the changes you did stayed local to your repository, e.g. you did not push any branches to some other repository. Rebasing is a great tool for you to arrange your local commits into a useful order before pushing it out into the world, but rebasing afterwards will mess up things for the git beginners like you.
Basing on this article you should:
create new branch which is based upon new version of master
git branch -b newmaster
merge your old feature branch into new one
git checkout newmaster
resolve conflict on new feature branch
The first two commands can be combined to git checkout -b newmaster
This way your history stays clear because you don’t need back merges. And you don’t need to be so super cautious since you don’t need git rebase
How do you delete a Git tag that has already been pushed?
You just need to push an ‘empty’ reference to the remote tag name:
Or, more expressively, use the --delete
option (or -d
if your git version is older than 1.8.0):
Note that git has tag namespace and branch namespace so you may use the same name for a branch and for a tag. If you want to make sure that you cannot accidentally remove the branch instead of the tag, you can specify full ref which will never delete a branch:
If you also need to delete the local tag, use:
Pushing a branch, tag, or other ref to a remote repository involves specifying “which repo, what source, what destination?”
A real world example where you push your master branch to the origin’s master branch is:
Which because of default paths, can be shortened to:
Tags work the same way:
Which can also be shortened to:
By omitting the source ref (the part before the colon), you push ‘nothing’ to the destination, deleting the ref on the remote end.
A more straightforward way is
IMO prefixing colon syntax is a little bit odd in this situation
If you have a remote tag v0.1.0
to delete, and your remote is origin
, then simply:
If you also need to delete the tag locally:
See Adam Franco’s answer for an explanation of Git’s unusual :
syntax for deletion.
So I added a folder to my .gitignore file.
Once I do a git status
it tells me
However, when I try to change branches I get the following:
My-MacBook-Pro:webapp marcamillion$ git checkout develop
error: The following untracked working tree files would be overwritten by checkout:
public/system/images/9/thumb/red-stripe.jpg
public/system/images/9/original/red-stripe.jpg
public/system/images/8/thumb/red-stripe-red.jpg
public/system/images/8/original/red-stripe-red.jpg
public/system/images/8/original/00-louis_c.k.-chewed_up-cover-2008.jpg
public/system/images/7/thumb/red-stripe-dark.jpg
public/system/images/7/original/red-stripe-dark.jpg
public/system/images/7/original/DSC07833.JPG
public/system/images/6/thumb/red-stripe-bw.jpg
public/system/images/6/original/website-logo.png
public/system/images/6/original/red-stripe-bw.jpg
public/system/images/5/thumb/Guy_Waving_Jamaican_Flag.jpg
public/system/images/5/original/logocompv-colored-squares-100px.png
public/system/images/5/original/Guy_Waving_Jamaican_Flag.jpg
public/system/images/4/thumb/DSC_0001.JPG
public/system/images/4/original/logo.png
public/system/images/4/original/DSC_0001.JPG
public/system/images/4/original/2-up.jpg
public/system/images/3/thumb/logo2.gif
public/system/images/3/original/logo2.gif
public/system/images/3/original/Guy_Waving_Jamaican_Flag.jpg
public/system/images/3/original/11002000962.jpg
public/system/images/2/thumb/Profile Pic.jpg
public/system/images/2/original/Profile Pic.jpg
public/system/images/2/original/02 Login Screen.jpg
public/system/images/1/original/Argentina-2010-World-Cup.jpg
Please move or remove them before you can switch branches.
Aborting
This is what my .gitignore file looks like:
How do I get this working so I can switch branches without deleting those files?
If I make a change, will it affect those files? In other words, if I came back to this branch afterwards would everything be perfect as up to my latest commit?
I don’t want to lose those files, I just don’t want them tracked.
It seems like you want the files ignored but they have already been commited. .gitignore has no effect on files that are already in the repo so they need to be removed with git rm --cached
. The --cached
will prevent it from having any effect on your working copy and it will just mark as removed the next time you commit. After the files are removed from the repo then the .gitignore will prevent them from being added again.
But you have another problem with your .gitignore, you are excessively using wildcards and its causing it to match less than you expect it to. Instead lets change the .gitignore and try this.
I hit this message as well. In my case, I didn’t want to keep the files, so this worked for me:
If you also want to remove files ignored by git, then execute the following command.
http://www.kernel.org/pub/software/scm/git/docs/git-clean.html
-x
means ignored files are also removed as well as files unknown to git.
-d
means remove untracked directories in addition to untracked files.
-f
is required to force it to run.
Warning: This will delete the local files that are not indexed
Just force it : git checkout -f another-branch
I need to add some rules to my .gitignore
file. However, I can’t find it in my project folder. Isn’t it created automatically by Xcode? If not, what command allows me to create one?
If you’re using Windows it will not let you create a file without a filename in Windows Explorer. It will give you the error “You must type a file name” if you try to rename a text file as .gitignore
To get around this I used the following steps
ren gitignore.txt .gitignore
Alternatively @HenningCash suggests in the comments
You can get around this Windows Explorer error by appending a dot to the filename without extension: .gitignore. will be automatically changed to .gitignore
As simple as things can (sometimes) be: Just add the following into your preferred command line interface (GNU Bash, Git Bash, etc.)
As @Wardy pointed out in the comments, touch
works on Windows as well as long as you provide the full path. This might also explain why it does not work for some users on Windows: The touch
command seems to not be in the $PATH
on some Windows versions per default.
Sometimes git suggests git rm --cached
to unstage a file, sometimes git reset HEAD file
. When should I use which?
EDIT:
D:\code\gt2>git init
Initialized empty Git repository in D:/code/gt2/.git/
D:\code\gt2>touch a
D:\code\gt2>git status
# On branch master
#
# Initial commit
#
# Untracked files:
# (use "git add <file>..." to include in what will be committed)
#
# a
nothing added to commit but untracked files present (use "git add" to track)
D:\code\gt2>git add a
D:\code\gt2>git status
# On branch master
#
# Initial commit
#
# Changes to be committed:
# (use "git rm --cached <file>..." to unstage)
#
# new file: a
#
D:\code\gt2>git commit -m a
[master (root-commit) c271e05] a
0 files changed, 0 insertions(+), 0 deletions(-)
create mode 100644 a
D:\code\gt2>touch b
D:\code\gt2>git status
# On branch master
# Untracked files:
# (use "git add <file>..." to include in what will be committed)
#
# b
nothing added to commit but untracked files present (use "git add" to track)
D:\code\gt2>git add b
D:\code\gt2>git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# new file: b
#
git rm --cached <filePath>
does not unstage a file, it actually stages the removal of the file(s) from the repo (assuming it was already committed before) but leaves the file in your working tree (leaving you with an untracked file).
git reset -- <filePath>
will unstage any staged changes for the given file(s).
That said, if you used git rm --cached
on a new file that is staged, it would basically look like you had just unstaged it since it had never been committed before.
git rm --cached
is used to remove a file from the index. In the case where the file is already in the repo, git rm --cached
will remove the file from the index, leaving it in the working directory and a commit will now remove it from the repo as well. Basically, after the commit, you would have unversioned the file and kept a local copy.
git reset HEAD file
( which by default is using the --mixed
flag) is different in that in the case where the file is already in the repo, it replaces the index version of the file with the one from repo (HEAD), effectively unstaging the modifications to it.
In the case of unversioned file, it is going to unstage the entire file as the file was not there in the HEAD. In this aspect git reset HEAD file
and git rm --cached
are same, but they are not same ( as explained in the case of files already in the repo)
To the question of Why are there 2 ways to unstage a file in git?
- there is never really only one way to do anything in git. that is the beauty of it :)
Quite simply:
git rm --cached <file>
makes git stop tracking the file completely (leaving it in the filesystem, unlike plain git rm
*)
git reset HEAD <file>
unstages any modifications made to the file since the last commit (but doesn’t revert them in the filesystem, contrary to what the command name might suggest**). The file remains under revision control.
If the file wasn’t in revision control before (i.e. you’re unstaging a file that you had just git add
ed for the first time), then the two commands have the same effect, hence the appearance of these being “two ways of doing something”.
* Keep in mind the caveat @DrewT mentions in his answer, regarding git rm --cached
of a file that was previously committed to the repository. In the context of this question, of a file just added and not committed yet, there’s nothing to worry about.
** I was scared for an embarrassingly long time to use the git reset command because of its name – and still today I often look up the syntax to make sure I don’t screw up. (update: I finally took the time to summarize the usage of git reset
in a tldr page, so now I have a better mental model of how it works, and a quick reference for when I forget some detail.)
I have cloned a remote Git repository to my laptop, then I wanted to add a tag so I ran
When I run git tag
on my laptop the tag mytag
is shown. I then want to push this to the remote repository so I have this tag on all my clients, so I run git push
but I got the message:
Everything up-to-date
And if I go to my desktop and run git pull
and then git tag
no tags are shown.
I have also tried to do a minor change on a file in the project, then push it to the server. After that I could pull the change from the server to my Desktop computer, but there’s still no tag when running git tag
on my desktop computer.
How can I push my tag to the remote repository so that all client computers can see it?
git push --follow-tags
This is a sane option introduced in Git 1.8.3:
It pushes both commits and only tags that are both:
This is sane because:
It is for those reasons that --tags
should be avoided.
Git 2.4 has added the push.followTags
option to turn that flag on by default which you can set with:
To push a single tag:
And the following command should push all tags (not recommended):
To push specific, one tag do following git push origin tag_name
How do I get git to use a proxy server?
I need to check out code from a git server, it shows “Request timed out” every time. How do I get around this?
Alternatively, how can I set a proxy server?
Command to use:
proxyuser
to your proxy user
proxypwd
to your proxy password
proxy.server.com
to the URL of your proxy server
8080
to the proxy port configured on your proxy server
If you decide at any time to reset this proxy and work without proxy:
Command to use:
Finally, to check the currently set proxy:
This worked for me, in windows XP behind a corporate firewall.
I didnt have to install any local proxy or any other software besides git v1.771 from http://code.google.com/p/msysgit/downloads/list?can=3
$ git config --global http.proxy http://proxyuser:proxypwd@proxy.server.com:8080
$ git config --system http.sslcainfo /bin/curl-ca-bundle.crt
$ git remote add origin https://mygithubuser:mygithubpwd@github.com/repoUser/repoName.git
$ git push origin master
proxyuser= the proxy user I was assigned by our IT dept, in my case it is the same windows user I use to log in to my PC, the Active Directory user
proxypwd= the password of my proxy user
proxy.server.com:8080 = the proxy name and port, I got it from Control Panel, Internet Options, Connections, Lan Settings button, Advanced button inside the Proxy Server section, use the servername and port on the first (http) row.
mygithubuser = the user I use to log in to github.com
mygithubpwd = the password for my github.com user
repoUser = the user owner of the repo
repoName = the name of the repo
Set a system variable named http_proxy
with the value of ProxyServer:Port
. That is the simplest solution. Respectively, use https_proxy
as daefu pointed out in the comments.
Setting gitproxy (as sleske mentions) is another option, but that requires a “command”, which is not as straightforward as the above solution.
References: http://bardofschool.blogspot.com/2008/11/use-git-behind-proxy.html
Recently, I have been asked to cherry-pick
a commit.
So what does cherry-picking a commit in git mean? How do you do it?
Cherry picking in Git means to choose a commit from one branch and apply it onto another.
This is in contrast with other ways such as merge
and rebase
which normally apply many commits onto another branch.
Make sure you are on the branch you want to apply the commit to.
sh git checkout master
Execute the following:
sh git cherry-pick <commit-hash>
N.B.:
If you cherry-pick from a public branch, you should consider using
This will generate a standardized commit message. This way, you (and your co-workers) can still keep track of the origin of the commit and may avoid merge conflicts in the future.If you have notes attached to the commit they do not follow the cherry-pick. To bring them over as well, You have to use:
sh git notes copy <from> <to>
Additional links:
This quote is taken from; Version Control with Git (Really great book, I encourage you to buy it if you are interested in git)
Edit: Since this answer is still getting impression, I would like to add very nice in action video tutorial about it:
Youtube: Introduction to Git cherry-pick
Using git cherry-pick The command git cherry-pick commit applies the changes introduced by the named commit on the current branch. It will introduce a new, distinct commit. Strictly speaking, using git cherry-pick doesn’t alter the existing history within a repository; instead, it adds to the history. As with other Git operations that introduce changes via the process of applying a diff, you may need to resolve conflicts to fully apply the changes from the given commit . The command git cherry-pick is typically used to introduce particular commits from one branch within a repository onto a different branch. A common use is to forward- or back-port commits from a maintenance branch to a development branch.
before:
after:
Cherry picking in Git is designed to apply some commit from one branch into another branch. It can be done if you eg. made a mistake and committed a change into wrong branch, but do not want to merge the whole branch. You can just eg. revert the commit and cherry-pick it on another branch.
To use it, you just need git cherry-pick hash
, where hash
is a commit hash from other branch.
For full procedure see: http://technosophos.com/2009/12/04/git-cherry-picking-move-small-code-patches-across-branches.html
I have two branches: master and dev
I want to create a “feature branch” from the dev branch.
Currently on the branch dev, I do:
… (some work)
But, after visualizing my branches, I got:
I mean that the branch seems ff merged, and I don’t understand why…
What I’m doing wrong?
Can you explain me please how you branch off from another branch and push back to the remote repository for the feature branch?
All that in a branching model like the one described here.
If you like the method in the link you’ve posted, have a look at Git Flow.
It’s a set of scripts he created for that workflow.
But to answer your question:
Creates MyFeature branch off dev. Do your work and then
Now merge your changes to dev without a fast-forward
Now push changes to the server
And you’ll see it how you want it.
If you want create a new branch from any of the existing branches in Git, just follow the options.
First change/checkout into the branch from where you want to create a new branch. For example, if you have the following branches like:
So if you want to create a new branch called “subbranch_of_b1” under the branch named “branch1” follow the steps:
Checkout or change into “branch1”
sh git checkout branch1
Now create your new branch called “subbranch_of_b1” under the “branch1” using the following command.
The above will create a new branch called subbranch_of_b1 under the branch branch1 (note thatbranch1
in the above command isn’t mandatory since the HEAD is currently pointing to it, you can precise it if you are on a different branch though).
Now after working with the subbranch_of_b1 you can commit and push or merge it locally or remotely.
push the subbranch_of_b1 to remote
Create a Branch
Create branch when master branch is checked out. Here commits in master will be synced to the branch you created.
$ git branch branch1
Create branch when branch1 is checked out . Here commits in branch1 will be synced to branch2
$ git branch branch2
Checkout a Branch
git checkout command switch branches or restore working tree files
$ git checkout branchname
Renaming a Branch
$ git branch -m branch1 newbranchname
Delete a Branch
$ git branch -d branch-to-delete
$ git branch -D branch-to-delete
( force deletion without checking the merged status )
Create and Switch Branch
$ git checkout -b branchname
Branches that are completely included
$ git branch --merged
************************** Branch Differences [ git diff branch1..branch2 ] ************************
Multiline difference
$ git diff master..branch1
Singleline difference
$ git diff --color-words branch1..branch2
I recently switched to synchronizing my repositories to https:// on GitHub (due to firewall issues), and it asks for a password every time.
Is there a way to cache the credentials, instead of authenticating every time that git push
?
Since Git 1.7.9 (released in late January 2012), there is a neat mechanism in Git to avoid having to type your password all the time for HTTP / HTTPS, called credential helpers. (Thanks to dazonic for pointing out this new feature in the comments below.)
With Git 1.7.9 or later, you can just use one of the following credential helpers:
… which tells Git to keep your password cached in memory for (by default) 15 minutes. You can set a longer timeout with:
(That example was suggested in the GitHub help page for Linux.) You can also store your credentials permanently if so desired, see the other answers below.
GitHub’s help also suggests that if you’re on Mac OS X and used Homebrew to install Git, you can use the native Mac OS X keystore with:
For Windows, there is a helper called Git Credential Manager for Windows or wincred in msysgit.
With Git for Windows 2.7.3+ (March 2016):
For Linux, you can use gnome-keyring
(or other keyring implementation such as KWallet).
With versions of Git before 1.7.9, this more secure option is not available, and you’ll need to change the URL that your origin
remote uses to include the password in this fashion:
… in other words with :password
after the username and before the @
.
You can set a new URL for your origin
remote with:
Make sure that you use https
, and you should be aware that if you do this, your GitHub password will be stored in plaintext in your .git
directory, which is obviously undesirable.
An alternative approach is to put your username and password in your ~/.netrc
file, although, as with keeping the password in the remote URL, this means that your password will be stored on the disk in plain text and is thus less secure and not recommended. However, if you want to take this approach, add the following line to your ~/.netrc
:
… replacing <hostname>
with the server’s hostname, and <username>
and <password>
with your username and password. Also remember to set restrictive file system permissions on that file:
Note that on Windows, this file should be called _netrc
, and you may need to define the %HOME% environment variable - for more details see:
You can also have Git store your credentials permanently using the following:
Note: While this is convenient, Git will store your credentials in clear text in a local file (.git-credentials) under your project directory (see below for the “home” directory). If you don’t like this, delete this file and switch to using the cache option.
If you want Git to resume to asking you for credentials every time it needs to connect to the remote repository, you can run this command:
To store the passwords in .git-credentials
in your %HOME%
directory as opposed to the project directory: use the --global
flag
Saving a password for a Git repository HTTPS URL is possible with a ~/.netrc
(Unix) or %HOME%/_netrc
(note the _
) on Windows.
But: That file would store your password in plain text.
Solution: Encrypt that file with GPG (GNU Privacy Guard), and make Git decrypt it each time it needs a password (for push
/pull
/fetch
/clone
operation).
Note: with Git 2.18 (Q2 2018), you now can customize the GPG used to decrypt the encrypted .netrc
file.
See commit 786ef50, commit f07eeed (12 May 2018) by Luis Marsano (`)</a>.<br> <sup>(Merged by <a href="https://github.com/gitster" rel="noreferrer">Junio C Hamano --
gitster` – in commit 017b7c5, 30 May 2018)
git-credential-netrc
: acceptgpg
option
git-credential-netrc
was hardcoded to decrypt with ‘gpg
’ regardless of the gpg.program option.
This is a problem on distributions like Debian that call modern GnuPG something else, like ‘gpg2
’
With Windows:
(Git has a gpg.exe
in its distribution, but using a full GPG installation includes a gpg-agent.exe
, which will memorize your passphrase associated to your GPG key.)
Install gpg4Win Lite
, the minimum gnupg command-line interface (take the most recent gpg4win-vanilla-2.X.Y-betaZZ.exe
), and complete your PATH with the GPG installation directory:
sh set PATH=%PATH%:C:\path\to\gpg copy C:\path\to\gpg\gpg2.exe C:\path\to\gpg\gpg.exe
(Note the ‘copy
’ command: Git will need a Bash script to execute the command ‘gpg
’. Since gpg4win-vanilla-2
comes with gpg2.exe
, you need to duplicate it.)
Create or import a GPG key, and trust it:
sh gpgp --import aKey # or gpg --gen-key
(Make sure to put a passphrase to that key.)
Install the credential helper script in a directory within your %PATH%
:
sh cd c:\a\fodler\in\your\path curl -o c:\prgs\bin\git-credential-netrc https://raw.githubusercontent.com/git/git/master/contrib/credential/netrc/git-credential-netrc
(Yes, this is a Bash script, but it will work on Windows since it will be called by Git.)
Make a _netrc file in clear text
```sh machine a_server.corp.com login a_login password a_password protocol https
machine a_server2.corp.com login a_login2 password a_password2 protocol https ```(Don’t forget the ‘protocol
’ part: ‘http
’ or ‘https
’ depending on the URL you will use.)
Encrypt that file:
sh gpg -e -r a_recipient _netrc
(You now can delete the _netrc
file, keeping only the _netrc.gpg
encrypted one.)
Use that encrypted file:
sh git config --local credential.helper "netrc -f C:/path/to/_netrc.gpg -v"
(Note the ‘/
’: C:\path\to...
wouldn’t work at all.) (You can use at first -v -d
to see what is going on.)
From now on, any Git command using an HTTP(S) URL which requires authentication will decrypt that _netrc.gpg
file and use the login/password associated to the server you are contacting. The first time, GPG will ask you for the passphrase of your GPG key, to decrypt the file. The other times, the gpg-agent launched automatically by the first GPG call will provide that passphrase for you.
That way, you can memorize several URLs/logins/passwords in one file, and have it stored on your disk encrypted.
I find it more convenient than a “cache” helper", where you need to remember and type (once per session) a different password for each of your remote services, for said password to be cached in memory.
How can I ignore directories or folders in Git using msysgit on Windows?
Create a file named .gitignore
in your project’s directory. Ignore directories by entering the directory name into the file (with a slash appended):
More info here.
By default windows explorer will display .gitignore
when in-fact the file name is .gitignore.txt
Git will not use .gitignore.txt
And you can’t rename the file to .gitignore
because explorer thinks its a file of type gitignore with no name.
Non command line solution:
You can rename a file to ".gitignore." and it will create ".gitignore"
It seems that for ignoring files and directories there are two main ways:
.gitignore
.gitignore
file into the root of your repo besides .git
folder (in Windows make sure you see the true file extension and then make .gitignore.
(with the point at the end to make empty file extension) )
~/.gitignore_global
and running git config --global core.excludesfile ~/.gitignore_global
to add this to your git config
git rm --cached filename
Repo exclude - For local files that do not need to be shared, you just add the file pattern or directory to the file .git/info/exclude
. Theses rules are not commited, so are not seen by other users more info here
[updated] To make exceptions in list of ignored files, see this question.
A rather unusual situation perhaps, but I want to specify a private SSH-key to use when executing a shell (git) command from the local computer.
Basically like this:
Or even better (in Ruby):
with_key("/home/christoffer/ssh_keys/theuser") do
sh("git clone git@github.com:TheUser/TheProject.git")
end
I have seen examples of connecting to a remote server with Net::SSH that uses a specified private key, but this is a local command. Is it possible?
Something like this should work (suggested by orip):
if you prefer subshells, you could try the following (though it is more fragile):
Git will invoke SSH which will find its agent by environment variable; this will, in turn, have the key loaded.
Alternatively, setting HOME
may also do the trick, provided you are willing to setup a directory that contains only a .ssh
directory as HOME
; this may either contain an identity.pub, or a config file setting IdentityFile.
None of these solutions worked for me.
Instead, I elaborate on @Martin v. Löwis ’s mention of setting a config
file for SSH.
SSH will look for the user’s ~/.ssh/config
file. I have mine setup as:
Host gitserv
Hostname remote.server.com
IdentityFile ~/.ssh/id_rsa.github
IdentitiesOnly yes # see NOTES below
And I add a remote git repository:
And then git commands work normally for me.
NOTES
IdentitiesOnly yes
is required to prevent the SSH default behavior of sending the identity file matching the default filename for each protocol. If you have a file named ~/.ssh/id_rsa
that will get tried BEFORE your ~/.ssh/id_rsa.github
without this option.
References
Other people’s suggestions about ~/.ssh/config
are extra complicated. It can be as simple as:
We’re using git submodules to manage a couple of large projects that have dependencies on many other libraries we’ve developed. Each library is a separate repo brought into the dependent project as a submodule. During development, we often want to just go grab the latest version of every dependent submodule.
Does git have a built in command to do this? If not, how about a Windows batch file or similar that can do it?
If it’s the first time you checkout a repo you need to use --init
first:
For git 1.8.2 or above the option --remote
was added to support updating to latest tips of remote branches:
This has the added benefit of respecting any “non default” branches specified in the .gitmodules
or .git/config
files (if you happen to have any, default is origin/master, in which case some of the other answers here would work as well).
For git 1.7.3 or above you can use (but the below gotchas around what update does still apply):
or:
if you want to pull your submodules to latest commits intead of what the repo points to.
See git-submodule(1) for details
a feature git first learned in 1.8.5.
For the first time you do need to run
git submodule update –init –recursive
from within the git repo directory, works best for me.
This will pull all latest including submodules.
git - the base command to perform any git command
submodule - Inspects, updates and manages submodules.
update - Update the registered submodules to match what the superproject
expects by cloning missing submodules and updating the working tree of the
submodules. The "updating" can be done in several ways depending on command
line options and the value of submodule.<name>.update configuration variable.
--init without the explicit init step if you do not intend to customize
any submodule locations.
--recursive is specified, this command will recurse into the registered
submodules, and update any nested submodules within.
from within the git repo directory, works best for me.
This will pull all latest including submodules.
--set-upstream
all the time? (score 918075 in 2013)I create a new branch in Git:
Push it:
Now say someone made some changes on the server and I want to pull from origin/my_branch
. I do:
But I get:
You asked me to pull without telling me which branch you
want to merge with, and 'branch.my_branch.merge' in
your configuration file does not tell me, either. Please
specify which branch you want to use on the command line and
try again (e.g. 'git pull <repository> <refspec>').
See git-pull(1) for details.
If you often merge with the same branch, you may want to
use something like the following in your configuration file:
[branch "my_branch"]
remote = <nickname>
merge = <remote-ref>
[remote "<nickname>"]
url = <url>
fetch = <refspec>
See git-config(1) for details.
I learned that I can make it work with:
But why do I need to do this for every branch I create? Isn’t it obvious that if I push my_branch
into origin/my_branch
, then I would want to pull origin/my_branch
into my_branch
? How can I make this the default behavior?
A shortcut, which doesn’t depend on remembering the syntax for git branch --set-upstream
1 is to do:
… the first time that you push that branch. Or, to push to the current branch to a branch of the same name (handy for an alias):
You only need to use -u
once, and that sets up the association between your branch and the one at origin
in the same way as git branch --set-upstream
does.
Personally, I think it’s a good thing to have to set up that association between your branch and one on the remote explicitly. It’s just a shame that the rules are different for git push
and git pull
.
1 It may sound silly, but I very frequently forget to specify the current branch, assuming that’s the default - it’s not, and the results are most confusing :)
Update 2012-10-11: Apparently I’m not the only person who found it easy to get wrong! Thanks to VonC for pointing out that git 1.8.0 introduces the more obvious git branch --set-upstream-to
, which can be used as follows, if you’re on the branch my_branch
:
… or with the short option:
This change, and its reasoning, is described in the release notes for git 1.8.0, release candidate 1:
It was tempting to saygit branch --set-upstream origin/master
, but that tells Git to arrange the local branchorigin/master
to integrate with the currently checked out branch, which is highly unlikely what the user meant. The option is deprecated; use the new--set-upstream-to
(with a short-and-sweet-u
) option instead.
You can make this happen with less typing. First, change the way your push works:
This will infer the origin my_branch
part, thus you can do:
Which will both create the remote branch with the same name and track it.
You can simply
in the first place. If you set branch.autosetupmerge
or branch.autosetuprebase
(my favorite) to always
(default is true
), my-branch
will automatically track origin/whatever
.
See git help config
.
Say I’m in a Git repository. I delete a file and commit that change. I continue working and make some more commits. Then, I find I need to restore that file.
I know I can checkout a file using git checkout HEAD^ foo.bar
, but I don’t really know when that file was deleted.
I’m hoping I don’t have to manually browse my logs, checkout the entire project for a given SHA and then manually copy that file into my original project checkout.
Find the last commit that affected the given path. As the file isn’t in the HEAD commit, this commit must have deleted it.
Then checkout the version at the commit before, using the caret (^
) symbol:
Or in one command, if $file
is the file in question.
If you are using zsh and have the EXTENDED_GLOB option enabled, the caret symbol won’t work. You can use ~1
instead.
git log --diff-filter=D --summary
to get all the commits which have deleted files and the files deleted;
git checkout $commit~1 path/to/file.ext
to restore the deleted file.
Where $commit
is the value of the commit you’ve found at step 1, e.g. e4cf499627
To restore all those deleted files in a folder enter the following command.
I am trying to set git up with http://danielmiessler.com/study/git/#website to manage my site.
I have gotten to the last step in the instructions: git push website +master:refs/heads/master
I am working using the git ming32 command line in win7
$ git push website +master:refs/heads/master
Bill@***.com's password:
Connection closed by 198.91.80.3
fatal: Could not read from remote repository.
Please make sure you have the correct access rights
and the repository exists.
One problem here may be that the program is looking for Bill@.com. when I connect via ssh to my site I have a different username( lets say ‘abc’). so maybe this should be abc@.com. If so I don’t know how to change this or if I can push under an alias
You can specify the username that SSH should send to the remote system as part of your remote’s URL. Put the username, followed by an @
, before the remote hostname.
Your ssh key most likely had been removed from ssh agent
where id_rsa is a ssh key associated with git repo
Make sure you have correct url in .git/config
If it’s your first push, you’ll need to set up correct upstream
You can check which key is used by:
The reply should contain something like this:
debug1: Next authentication method: publickey
debug1: Offering RSA public key: ~/.ssh/id_rsa
...
You've successfully authenticated, but GitHub does not provide shell access.
Also it’s possible to define rules for ssh in ~/.ssh/config
, e.g. based on aliases:
Host github
HostName github.com
User git
IdentityFile "~/.ssh/id_rsa"
Host git
HostName github.com
User git
IdentityFile "~/.ssh/some_other_id"
You can set connect to different ports, use different username etc. for each alias.
I’d like to move the last several commits I’ve committed to master to a new branch and take master back to before those commits were made. Unfortunately, my Git-fu is not strong enough yet, any help?
I.e. How can I go from this
to this?
If you want to move your commits to an existing branch, it will look like this:
git checkout existingbranch
git merge master # Bring the commits here
git checkout master
git reset --keep HEAD~3 # Move master back by 3 commits.
git checkout existingbranch
The --keep
option preserves any uncommitted changes that you might have in unrelated files, or aborts if those changes would have to be overwritten – similarly to what git checkout
does. If it aborts, git stash
your changes and retry, or use --hard
to lose the changes (even from files that didn’t change between the commits!)
This method works by creating a new branch with the first command (git branch newbranch
) but not switching to it. Then we roll back the current branch (master) and switch to the new branch to continue working.
git branch newbranch # Create a new branch, containing all current commits
git reset --keep HEAD~3 # Move master back by 3 commits (Make sure you know how many commits you need to go back)
git checkout newbranch # Go to the new branch that still has the desired commits
# Warning: after this it's not safe to do a rebase in newbranch without extra care.
But do make sure how many commits to go back. Alternatively, instead of HEAD~3
, you can simply provide the hash of the commit (or the reference like origin/master
) you want to revert back to, e.g:
WARNING: With Git version 2.0 and later, if you later git rebase
the new branch upon the original (master
) branch, you may need an explicit --no-fork-point
option during the rebase to avoid losing the commits you moved from the master branch. Having branch.autosetuprebase always
set makes this more likely. See John Mellor’s answer for details.
For those wondering why it works (as I was at first):
You want to go back to C, and move D and E to the new branch. Here’s what it looks like at first:
After git branch newBranch
:
After git reset --hard HEAD~2
:
Since a branch is just a pointer, master pointed to the last commit. When you made newBranch, you simply made a new pointer to the last commit. Then using git reset
you moved the master pointer back two commits. But since you didn’t move newBranch, it still points to the commit it originally did.
The method exposed by sykora is the best option in this case. But sometimes is not the easiest and it’s not a general method. For a general method use git cherry-pick:
To achieve what OP wants, its a 2-step process:
newbranch
Execute
Note the hashes of (say 3) commits you want on newbranch
. Here I shall use:
C commit: 9aa1233
D commit: 453ac3d
E commit: 612ecb3
Note: You can use the first seven characters or the whole commit hash
newbranch
git cherry-pick applies those three commits to newbranch.
Does anybody know how to easily undo a git rebase?
The only way that comes to mind is to go at it manually:
In my current situation this is gonna work because I can easily spot commits from both branches (one was my stuff, the other was my colleague’s stuff).
However my approach strikes me as suboptimal and error-prone (let’s say I had just rebased with 2 of my own branches).
Any ideas?
Clarification: I’m talking about a rebase during which a bunch of commits were replayed. Not only one.
The easiest way would be to find the head commit of the branch as it was immediately before the rebase started in the reflog…
and to reset the current branch to it (with the usual caveats about being absolutely sure before reseting with the --hard
option).
Suppose the old commit was HEAD@{5}
in the ref log:
In Windows, you may need to quote the reference:
You can check the history of the candidate old head by just doing a git log HEAD@{5}
(Windows: git log "HEAD@{5}"
).
If you’ve not disabled per branch reflogs you should be able to simply do git reflog branchname@{1}
as a rebase detaches the branch head before reattaching to the final head. I would double check this, though as I haven’t verified this recently.
Per default, all reflogs are activated for non-bare repositories:
Actually, rebase saves your starting point to ORIG_HEAD
so this is usually as simple as:
However, the reset
, rebase
and merge
all save your original HEAD
pointer into ORIG_HEAD
so, if you’ve done any of those commands since the rebase you’re trying to undo then you’ll have to use the reflog.
Charles’s answer works, but you may want to do this:
to clean up after the reset
.
Otherwise, you may get the message “Interactive rebase already started
”.
I’m new at the branching complexities of Git. I always work on a single branch and commit changes and then periodically push to my remote origin.
Somewhere recently, I did a reset of some files to get them out of commit staging, and later did a rebase -i
to get rid of a couple recent local commits. Now I’m in a state I don’t quite understand.
In my working area, git log
shows exactly what I’d expect– I’m on the right train with the commits I didn’t want gone, and new ones there, etc.
But I just pushed to the remote repository, and what’s there is different– a couple of the commits I’d killed in the rebase got pushed, and the new ones committed locally aren’t there.
I think “master/origin” is detached from HEAD, but I’m not 100% clear on what that means, how to visualize it with the command line tools, and how to fix it.
First, let’s clarify what HEAD is and what it means when it is detached.
HEAD is the symbolic name for the currently checked out commit. When HEAD is not detached (the “normal”1 situation: you have a branch checked out), HEAD actually points to a branch’s “ref” and the branch points to the commit. HEAD is thus “attached” to a branch. When you make a new commit, the branch that HEAD points to is updated to point to the new commit. HEAD follows automatically since it just points to the branch.
git symbolic-ref HEAD
yields refs/heads/master
git rev-parse refs/heads/master
yield 17a02998078923f2d62811326d130de991d1a95a
git rev-parse HEAD
also yields 17a02998078923f2d62811326d130de991d1a95a
We have HEAD
→ refs/heads/master
→ 17a02998078923f2d62811326d130de991d1a95a
When HEAD is detached, it points directly to a commit—instead of indirectly pointing to one through a branch. You can think of a detached HEAD as being on an unnamed branch.
git symbolic-ref HEAD
fails with fatal: ref HEAD is not a symbolic ref
git rev-parse HEAD
yields 17a02998078923f2d62811326d130de991d1a95a
We have HEAD
→ 17a02998078923f2d62811326d130de991d1a95a
The important thing to remember with a detached HEAD is that if the commit it points to is otherwise unreferenced (no other ref can reach it), then it will become “dangling” when you checkout some other commit. Eventually, such dangling commits will be pruned through the garbage collection process (by default, they are kept for at least 2 weeks and may be kept longer by being referenced by HEAD’s reflog).
1 It is perfectly fine to do “normal” work with a detached HEAD, you just have to keep track of what you are doing to avoid having to fish dropped history out of the reflog.
The intermediate steps of an interactive rebase are done with a detached HEAD (partially to avoid polluting the active branch’s reflog). If you finish the full rebase operation, it will update your original branch with the cumulative result of the rebase operation and reattach HEAD to the original branch. My guess is that you never fully completed the rebase process; this will leave you with a detached HEAD pointing to the commit that was most recently processed by the rebase operation.
To recover from your situation, you should create a branch that points to the commit currently pointed to by your detached HEAD:
(these two commands can be abbreviated as git checkout -b temp
)
This will reattach your HEAD to the new temp
branch.
Next, you should compare the current commit (and its history) with the normal branch on which you expected to be working:
git log --graph --decorate --pretty=oneline --abbrev-commit master origin/master temp
git diff master temp
git diff origin/master temp
(You will probably want to experiment with the log options: add -p
, leave off --pretty=…
to see the whole log message, etc.)
If your new temp
branch looks good, you may want to update (e.g.) master
to point to it:
(these two commands can be abbreviated as git checkout -B master temp
)
You can then delete the temporary branch:
Finally, you will probably want to push the reestablished history:
You may need to add --force
to the end of this command to push if the remote branch can not be “fast-forwarded” to the new commit (i.e. you dropped, or rewrote some existing commit, or otherwise rewrote some bit of history).
If you were in the middle of a rebase operation you should probably clean it up. You can check whether a rebase was in process by looking for the directory .git/rebase-merge/
. You can manually clean up the in-progress rebase by just deleting that directory (e.g. if you no longer remember the purpose and context of the active rebase operation). Usually you would use git rebase --abort
, but that does some extra resetting that you probably want to avoid (it moves HEAD back to the original branch and resets it back to the original commit, which will undo some of the work we did above).
Just do this:
Or, if you have changes that you want to keep, do this:
I ran into this issue and when I read in the top voted answer:
HEAD is the symbolic name for the currently checked out commit.
I thought: Ah-ha! If HEAD
is the symbolic name for the currenlty checkout commit, I can reconcile it against master
by rebasing it against master
:
This command:
master
HEAD
back to the point HEAD
diverged from master
master
The end result is that all commits that were in HEAD
but not master
are then also in master
. master
remains checked out.
Regarding the remote:
a couple of the commits I’d killed in the rebase got pushed, and the new ones committed locally aren’t there.
The remote history can no longer be fast-forwarded using your local history. You’ll need to force-push (git push -f
) to overwrite the remote history. If you have any collaborators, it usually makes sense to coordinate this with them so everyone is on the same page.
After you push master
to remote origin
, your remote tracking branch origin/master
will be updated to point to the same commit as master
.
I have a repository with a file, Hello.java
. When I compile it, an additional Hello.class
file is generated.
I created an entry for Hello.class
in a .gitignore
file. However, the file still appears to be tracked.
How can I make Git ignore Hello.class
?
The problem is that .gitignore
ignores just files that weren’t tracked before (by git add
). Run git reset name_of_file
to unstage the file and keep it. In case you want to also remove the given file from the repository (after pushing), use git rm --cached name_of_file
.
How to ignore new files
Globally
Add the path(s) to your file(s) which you would like to ignore to your .gitignore file (and commit them). These file entries will also apply to others checking out the repo.
Locally
Add the path(s) to your file(s) which you would like to ignore to your .git/info/exclude file. These file entries will only apply to your local working copy.
How to ignore changed files (temporarily)
In order to ignore changed files to being listed as modified, you can use the following git command:
To revert that ignorance use the following command:
Add the following line to .gitignore:
This will exclude Hello.class from git. If you have already committed it, run the following command:
If you want to exclude all class files from git, add the following line to .gitignore:
When I do git diff COMMIT
I see the changes between that commit and HEAD (as far as I know), but I would like to see the changes that were made by that single commit.
I haven’t found any obvious options on diff
/ log
that will give me that output.
To see the diff for a particular COMMIT
hash:
git diff COMMIT~ COMMIT
will show you the difference between that COMMIT
’s ancestor and the COMMIT
. See the man pages for git diff for details about the command and gitrevisions about the ~
notation and its friends.
Alternatively, git show COMMIT
will do something very similar. (The commit’s data, including its diff - but not for merge commits.) See the git show manpage.
As mentioned in “Shorthand for diff of git commit with its parent?”, you can also use git diff
with:
or
With git show, you would need (in order to focus on diff alone) to do:
The COMMIT
parameter is a commit-ish:
A commit object or an object that can be recursively dereferenced to a commit object. The following are all commit-ishes: a commit object, a tag object that points to a commit object, a tag object that points to a tag object that points to a commit object, etc.
See gitrevision “SPECIFYING REVISIONS” to reference a commit-ish.
See also “What does tree-ish mean in Git?”.
You can also try this easy way:
Possible Duplicate:
git replacing LF with CRLF
When I create a new rails application I’m seeing a warning in git about LF replacement. I do git init git add .
and then boom! I see this pop up for almost all files. I usually just keep going and build my application and it disappears after many changes to files.
Example:
The file will have its original line endings in your working directory. warning: LF will be replaced by CRLF in Gemfile.
The file will have its original line endings in your working directory. warning: LF will be replaced by CRLF in Gemfile.lock.
The file will have its original line endings in your working directory. warning: LF will be replaced by CRLF in README.
What’s the difference between LF and CRLF?
Should I be concerned about this in the long run or just ignore it and keep going as I usually do?
In Unix systems the end of a line is represented with a line feed (LF). In windows a line is represented with a carriage return (CR) and a line feed (LF) thus (CRLF). when you get code from git that was uploaded from a unix system they will only have an LF.
If you are a single developer working on a windows machine, and you don’t care that git automatically replaces LFs to CRLFs, you can turn this warning off by typing the following in the git command line
If you want to make an intelligent decision how git should handle this, read the documentation
Here is a snippet
Formatting and Whitespace
Formatting and whitespace issues are some of the more frustrating and subtle problems that many developers encounter when collaborating, especially cross-platform. It’s very easy for patches or other collaborated work to introduce subtle whitespace changes because editors silently introduce them, and if your files ever touch a Windows system, their line endings might be replaced. Git has a few configuration options to help with these issues.
If you’re programming on Windows and working with people who are not (or vice-versa), you’ll probably run into line-ending issues at some point. This is because Windows uses both a carriage-return character and a linefeed character for newlines in its files, whereas Mac and Linux systems use only the linefeed character. This is a subtle but incredibly annoying fact of cross-platform work; many editors on Windows silently replace existing LF-style line endings with CRLF, or insert both line-ending characters when the user hits the enter key.
Git can handle this by auto-converting CRLF line endings into LF when you add a file to the index, and vice versa when it checks out code onto your filesystem. You can turn on this functionality with the core.autocrlf setting. If you’re on a Windows machine, set it to true – this converts LF endings into CRLF when you check out code:
If you’re on a Linux or Mac system that uses LF line endings, then you don’t want Git to automatically convert them when you check out files; however, if a file with CRLF endings accidentally gets introduced, then you may want Git to fix it. You can tell Git to convert CRLF to LF on commit but not the other way around by setting core.autocrlf to input:
This setup should leave you with CRLF endings in Windows checkouts, but LF endings on Mac and Linux systems and in the repository.
If you’re a Windows programmer doing a Windows-only project, then you can turn off this functionality, recording the carriage returns in the repository by setting the config value to false:
If you want, you can deactivate this feature in your git core config using
But it would be better to just get rid of the warnings using
I’ve been using Subversion for a few years and after using SourceSafe, I just love Subversion. Combined with TortoiseSVN, I can’t really imagine how it could be any better.
Yet there’s a growing number of developers claiming that Subversion has problems and that we should be moving to the new breed of distributed version control systems, such as Git.
How does Git improve upon Subversion?
Git is not better than Subversion. But is also not worse. It’s different.
The key difference is that it is decentralized. Imagine you are a developer on the road, you develop on your laptop and you want to have source control so that you can go back 3 hours.
With Subversion, you have a Problem: The SVN Repository may be in a location you can’t reach (in your company, and you don’t have internet at the moment), you cannot commit. If you want to make a copy of your code, you have to literally copy/paste it.
With Git, you do not have this problem. Your local copy is a repository, and you can commit to it and get all benefits of source control. When you regain connectivity to the main repository, you can commit against it.
This looks good at first, but just keep in mind the added complexity to this approach.
Git seems to be the “new, shiny, cool” thing. It’s by no means bad (there is a reason Linus wrote it for the Linux Kernel development after all), but I feel that many people jump on the “Distributed Source Control” train just because it’s new and is written by Linus Torvalds, without actually knowing why/if it’s better.
Subversion has Problems, but so does Git, Mercurial, CVS, TFS or whatever.
Edit: So this answer is now a year old and still generates many upvotes, so I thought I’ll add some more explanations. In the last year since writing this, Git has gained a lot of momentum and support, particularly since sites like GitHub really took off. I’m using both Git and Subversion nowadays and I’d like to share some personal insight.
First of all, Git can be really confusing at first when working decentralized. What is a remote? and How to properly set up the initial repository? are two questions that come up at the beginning, especially compared to SVN’s simple “svnadmin create”, Git’s “git init” can take the parameters –bare and –shared which seems to be the “proper” way to set up a centralized repository. There are reasons for this, but it adds complexity. The documentation of the “checkout” command is very confusing to people changing over - the “proper” way seems to be “git clone”, while “git checkout” seems to switch branches.
Git REALLY shines when you are decentralized. I have a server at home and a Laptop on the road, and SVN simply doesn’t work well here. With SVN, I can’t have local source control if I’m not connected to the repository (Yes, I know about SVK or about ways to copy the repo). With Git, that’s the default mode anyway. It’s an extra command though (git commit commits locally, whereas git push origin master pushes the master branch to the remote named “origin”).
As said above: Git adds complexity. Two modes of creating repositories, checkout vs. clone, commit vs. push… You have to know which commands work locally and which work with “the server” (I’m assuming most people still like a central “master-repository”).
Also, the tooling is still insufficient, at least on Windows. Yes, there is a Visual Studio AddIn, but I still use git bash with msysgit.
SVN has the advantage that it’s MUCH simpler to learn: There is your repository, all changes to towards it, if you know how to create, commit and checkout and you’re ready to go and can pickup stuff like branching, update etc. later on.
Git has the advantage that it’s MUCH better suited if some developers are not always connected to the master repository. Also, it’s much faster than SVN. And from what I hear, branching and merging support is a lot better (which is to be expected, as these are the core reasons it was written).
This also explains why it gains so much buzz on the Internet, as Git is perfectly suited for Open Source projects: Just Fork it, commit your changes to your own Fork, and then ask the original project maintainer to pull your changes. With Git, this just works. Really, try it on Github, it’s magic.
What I also see are Git-SVN Bridges: The central repository is a Subversion repo, but developers locally work with Git and the bridge then pushes their changes to SVN.
But even with this lengthy addition, I still stand by my core message: Git is not better or worse, it’s just different. If you have the need for “Offline Source Control” and the willingness to spend some extra time learning it, it’s fantastic. But if you have a strictly centralized Source Control and/or are struggling to introduce Source Control in the first place because your co-workers are not interested, then the simplicity and excellent tooling (at least on Windows) of SVN shine.
With Git, you can do practically anything offline, because everybody has their own repository.
Making branches and merging between branches is really easy.
Even if you don’t have commit rights for a project, you can still have your own repository online, and publish “push requests” for your patches. Everybody who likes your patches can pull them into their project, including the official maintainers.
It’s trivial to fork a project, modify it, and still keep merging in the bugfixes from the HEAD branch.
Git works for the Linux kernel developers. That means it is really fast (it has to be), and scales to thousands of contributors. Git also uses less space (up to 30 times less space for the Mozilla repository).
Git is very flexible, very TIMTOWTDI (There is more than one way to do it). You can use whatever workflow you want, and Git will support it.
Finally, there’s GitHub, a great site for hosting your Git repositories.
Drawbacks of Git:
Other answers have done a good job of explaining the core features of Git (which are great). But there’s also so many little ways that Git behaves better and helps keep my life more sane. Here are some of the little things:
I’m on Mac Snow Leopard and I just installed git
.
I just tried
but that gives me this error:
Initialized empty Git repository in `/Users/username/Documents/cakebook/.git/`
Permission denied (publickey).
fatal: The remote end hung up unexpectedly
What am I missing?
I’ve also tried doing ssh-keygen
with no passphase but still same error.
the user have not generated a ssh public/private key pair set before ?
This info is working on theChaw but can be applied to all other git repositories which support SSH pubkey authentications. (See gitolite, gitlab or github for example.)
First start by setting up your own public/private key pair set. This can use either DSA or RSA, so basically any key you setup will work. On most systems you can use ssh-keygen.
Thats it you should be good to clone and checkout.
First you’ll want to cd into your .ssh directory. Open up the terminal and run:
cd ~/.ssh && ssh-keygen
Next you need to copy this to your clipboard.
- On OS X run:
cat id_rsa.pub | pbcopy
- On Linux run:
cat id_rsa.pub | xclip
- On Windows (via Cygwin/Git Bash) run:
cat id_rsa.pub | clip
- Add your key to your account via the website.
Finally setup your .gitconfig.
git config --global user.name "bob"
git config --global user.email bob@...
(don’t forget to restart your command line to make sure the config is reloaded)
Further information can be found on https://help.github.com/articles/generating-ssh-keys (thanks to @Lee Whitney) -
the user have generated a ssh public/private key pair set before ?
eval $(ssh-agent -s)
tell where the keys are located
ssh-add ~/.ssh/id_rsa
More extensive troubleshooting and even automated fixing can be done with:
Source: https://help.github.com/articles/error-permission-denied-publickey/
This error can happen when you are accessing the SSH URL (Read/Write) instead of Git Read-Only URL but you have no write access to that repo.
Sometimes you just want to clone your own repo, e.g. deploy to a server. In this case you actually only need READ-ONLY access. But since that’s your own repo, GitHub may display SSH URL if that’s your preference. In this situation, if your remote host’s public key is not in your GitHub SSH Keys, your access will be denied, which is expected to happen.
An equivalent case is when you try cloning someone else’s repo to which you have no write access with SSH URL.
In a word, if your intent is to clone-only a repo, use HTTPS URL (https://github.com/{user_name}/{project_name}.git
) instead of SSH URL (git@github.com:{user_name}/{project_name}.git
), which avoids (unnecessary) public key validation.
Update: GitHub is displaying HTTPS as the default protocol now and this move can probably reduce possible misuse of SSH URLs.
How can I add an empty directory (that contains no files) to a Git repository?
Another way to make a directory stay (almost) empty (in the repository) is to create a .gitignore
file inside that directory that contains these four lines:
Then you don’t have to get the order right the way that you have to do in m104’s solution.
This also gives the benefit that files in that directory won’t show up as “untracked” when you do a git status.
Making @GreenAsJade’s comment persistent:
I think it’s worth noting that this solution does precisely what the question asked for, but is not perhaps what many people looking at this question will have been looking for. This solution guarantees that the directory remains empty. It says “I truly never want files checked in here”. As opposed to “I don’t have any files to check in here, yet, but I need the directory here, files may be coming later”.
You can’t. See the Git FAQ.
Currently the design of the git index (staging area) only permits files to be listed, and nobody competent enough to make the change to allow empty directories has cared enough about this situation to remedy it.
Directories are added automatically when adding files inside them. That is, directories never have to be added to the repository, and are not tracked on their own.
You can say “
git add <dir>
” and it will add files in there.If you really need a directory to exist in checkouts you should create a file in it. .gitignore works well for this purpose; you can leave it empty, or fill in the names of files you expect to show up in the directory.
Create an empty file called .gitkeep
in the directory, and add that.
I’ve got a project checked locally from GitHub, and that remote repository has since had changes made to it. What’s the correct command to update my local copy with the latest changes?
Probably:
This should work for every default repo:
If your default branch is different than master
, you will need to specify the branch name:
However you’ll need to merge any changes into your local branches. If you’re on a branch that’s tracking a remote branch on Github, then
will first do a fetch, and then merge in the tracked branch
How can I go about rolling back to a specific commit in git?
The best answer someone could give me was to use git revert
X times until I reach the desired commit.
So let’s say I want to revert back to a commit that’s 20 commits old, I’d have to run it 20 times.
Is there an easier way to do this?
I can’t use reset because this repository is public.
Try this:
where [revision]
is the commit hash (for example: 12345678901234567890123456789012345678ab
).
Don’t forget the .
at the end, very important. This will apply changes to the whole tree. You should execute this command in the git project root. If you are in any sub directory, then this command only changes the files in the current directory. Then commit and you should be good.
You can undo this by
that will delete all modifications from the working directory and staging area.
To rollback to a specific commit:
To rollback 10 commits back:
You can use “git revert” as in the following post if you don’t want to rewrite the history
Well, I guess the question is, what do you mean by ‘roll back’? If you can’t reset
because it’s public and you want to keep the commit history intact, do you mean you just want your working copy to reflect a specific commit? Use git checkout
and the commit hash.
Edit: As was pointed out in the comments, using git checkout
without specifying a branch will leave you in a “no branch” state. Use git checkout <commit> -b <branchname>
to checkout into a branch, or git checkout <commit> .
to checkout into the current branch.
Anybody seen this error and know what to do?
I’m using the terminal, I’m in the root, the GitHub repository exists and I don’t know what to do now.
GitHub isn’t able to authenticate you. So, either you aren’t setup with an SSH key, because you haven’t set one up on your machine, or your key isn’t associated with your GitHub account.
You can also use the HTTPS URL instead of the SSH/git URL to avoid having to deal with SSH keys. This is GitHub’s recommended method.
Further, GitHub has a help page specifically for that error message, and explains in more detail everything you could check.
Did you create a config file in your ~/.ssh directory? It should have contents like these:
Assuming that you created an ssh key named github_rsa
and uploaded it to GitHub…
NOTE: You must follow this way of explicit configuration if you have more than 1 key (2 and more) in your ~/.ssh/ directory. If you don’t specify key this way, then first key in order is taken and used for github authentication, so it depends on the key file name then.
You need to generate an SSH key (if you don’t have one) and associate the public key with your Github account. See Github’s own documentation.
I made some updates on my local machine, pushed them to a remote repository, and now I’m trying to pull the changes to the server and I get the message;
error: Your local changes to the following files would be overwritten by merge:
wp-content/w3tc-config/master.php
Please, commit your changes or stash them before you can merge.
So I ran,
and tried again and I get the same message. I’m assuming that w3tc
changed something in the config file on the server. I don’t care whether the local copy or remote copy goes on the server (I suppose the remote one is best), I just want to be able to merge the rest of my changes (plugin updates).
Any ideas?
You can’t merge with local modifications. Git protects you from losing potentially important changes.
You have three options:
sh git commit -m "My message"
Stashing acts as a stack, where you can push changes, and you pop them in reverse order.
To stash, type
Do the merge, and then pull the stash:
sh git stash pop
using git reset --hard
or git checkout -t -f remote/branch
git checkout filename
The first command stores your changes temporarily in the stash and removes them from the working directory.
The second command switches branches.
The third command restores the changes which you have stored in the stash (the --index
option is useful to make sure that staged files are still staged).
You can try one of the following methods:
For simple changes try rebasing on top of it while pulling the changes, e.g.
So it’ll apply your current branch on top of the upstream branch after fetching.
This is equivalent to: checkout master
, fetch
and rebase origin/master
git commands.
This is a potentially dangerous mode of operation. It rewrites history, which does not bode well when you published that history already. Do not use this option unless you have read git-rebase(1)
carefully.
If you don’t care about your local changes, you can switch to other branch temporary (with force), and switch it back, e.g.
If you don’t care about your local changes, try to reset it to HEAD (original state), e.g.
If above won’t help, it may be rules in your git normalization file (.gitattributes
) so it’s better to commit what it says. Or your file system doesn’t support permissions, so you’ve to disable filemode
in your git config.
Related: How do I force “git pull” to overwrite local files?
I have a directory structure like this:
Inside main and tools, and any other directory, at any level, there can be a ‘bin’ directory, which I want to ignore (and I want to ignore everything under it too). I’ve tried each of these patterns in .gitignore but none of them work:
/**/bin/**/*
/./**/bin/**/*
./**/bin/**/*
**/bin/**/*
*/bin/**/*
bin/**/*
/**/bin/* #and the others with just * at the end too
Can anyone help me out? The first pattern (the one I think should be working) works just fine if I do this:
But I don’t want to have an entry for every top-level directory and I don’t want to have to modify .gitignore every time I add a new one.
This is on Windows using the latest msysgit.
EDIT: one more thing, there are files and directories that have the substring ‘bin’ in their names, I don’t want those to be ignored :)
Before version 1.8.2, **
didn’t have any special meaning in the .gitignore
. As of 1.8.2 git supports **
to mean zero or more sub-directories (see release notes).
The way to ignore all directories called bin anywhere below the current level in a directory tree is with a .gitignore
file with the pattern:
In the man
page, there an example of ignoring a directory called foo
using an analogous pattern.
Edit: If you already have any bin folders in your git index which you no longer wish to track then you need to remove them explicitly. Git won’t stop tracking paths that are already being tracked just because they now match a new .gitignore
pattern. Execute a folder remove (rm) from index only (–cached) recursivelly (-r). Command line example for root bin folder:
The .gitignore
of your dream seems to be:
on the top level.
I think it is worth to mention for git beginners:
If you already have a file checked in, and you want to ignore it, Git will not ignore the file if you add a rule later. In those cases, you must untrack the file first, by running the following command in your terminal:
git rm --cached
So if you want add to ignore some directories in your local repository (which already exist) after editing .gitignore you want to run this on your root dir
It will basically ‘refresh’ your local repo and unstage ignored files.
See:
http://git-scm.com/docs/git-rm,
https://help.github.com/articles/ignoring-files/
I would prefer to write my commit messages in Vim, but it is opening them in Emacs.
How do I configure Git to always use Vim? Note that I want to do this globally, not just for a single project.
If you want to set the editor only for Git, do either (you don’t need both):
core.editor
in your Git config: git config --global core.editor "vim"
GIT_EDITOR
environment variable: export GIT_EDITOR=vim
If you want to set the editor for Git and also other programs, set the standardized VISUAL
and EDITOR
environment variables*:
* Setting both is not necessarily needed, but some programs may not use the more-correct VISUAL
. See VISUAL
vs. EDITOR
.
For Sublime Text: Add this to the .gitconfig
. The --wait
is important. (it allows to type text in sublime and will wait for save/close event.
‘subl’ can be replaced by the full path of the executable but is usually available when correctly installed.
Copy paste this:
In case you’d like to know what you’re doing. From man git-commit
:
ENVIRONMENT AND CONFIGURATION VARIABLES The editor used to edit the commit log message will be chosen from the
GIT_EDITOR
environment variable, thecore.editor
configuration variable, theVISUAL
environment variable, or theEDITOR
environment variable (in that order).
On Ubuntu and also Debian (thanks @MichielB) changing the default editor is also possible by running:
Which will prompt the following:
There are 4 choices for the alternative editor (providing /usr/bin/editor).
Selection Path Priority Status
------------------------------------------------------------
0 /bin/nano 40 auto mode
1 /bin/ed -100 manual mode
2 /bin/nano 40 manual mode
* 3 /usr/bin/vim.basic 30 manual mode
4 /usr/bin/vim.tiny 10 manual mode
Press enter to keep the current choice[*], or type selection number:
I have a project in which I have to change the mode of files with chmod
to 777 while developing, but which should not change in the main repo.
Git picks up on chmod -R 777 .
and marks all files as changed. Is there a way to make Git ignore mode changes that have been made to files?
Try:
From git-config(1):
core.fileMode Tells Git if the executable bit of files in the working tree is to be honored. Some filesystems lose the executable bit when a file that is marked as executable is checked out, or checks out a non-executable file with executable bit on. git-clone(1) or git-init(1) probe the filesystem to see if it handles the executable bit correctly and this variable is automatically set as necessary. A repository, however, may be on a filesystem that handles the filemode correctly, and this variable is set to true when created, but later may be made accessible from another environment that loses the filemode (e.g. exporting ext4 via CIFS mount, visiting a Cygwin created repository with Git for Windows or Eclipse). In such a case it may be necessary to set this variable to false. See git-update-index(1). The default is true (when core.filemode is not specified in the config file).
The -c
flag can be used to set this option for one-off commands:
And the --global
flag will make it be the default behavior for the logged in user.
Changes of the global setting won’t be applied to existing repositories. Additionally, git clone
and git init
explicitly set core.fileMode
to true
in the repo config as discussed in Git global core.fileMode false overridden locally on clone
core.fileMode
is not the best practice and should be used carefully. This setting only covers the executable bit of mode and never the read/write bits. In many cases you think you need this setting because you did something like chmod -R 777
, making all your files executable. But in most projects most files don’t need and should not be executable for security reasons.
The proper way to solve this kind of situation is to handle folder and file permission separately, with something like:
find . -type d -exec chmod a+rwx {} \; # Make folders traversable and read/write
find . -type f -exec chmod a+rw {} \; # Make files read/write
If you do that, you’ll never need to use core.fileMode
, except in very rare environment.
undo mode change in working tree:
git diff --summary | grep --color 'mode change 100755 => 100644' | cut -d' ' -f7- | xargs -d'\n' chmod +x
git diff --summary | grep --color 'mode change 100644 => 100755' | cut -d' ' -f7- | xargs -d'\n' chmod -x
Or in mingw-git
If you want to set this option for all of your repos, use the --global
option.
If this does not work you are probably using a newer version of git so try the --add
option.
If you run it without the –global option and your working directory is not a repo, you’ll get
I “accidentally” pushed a commit to GitHub.
Is it possible to remove this commit?
I want to revert my GitHub repository as it was before this commit.
Note: please see alternative to
git rebase -i
in the comments below—git reset --soft HEAD^
First, remove the commit on your local repository. You can do this using git rebase -i
. For example, if it’s your last commit, you can do git rebase -i HEAD~2
and delete the second line within the editor window that pops up.
Then, force push to GitHub by using git push origin +branchName --force
See Git Magic Chapter 5: Lessons of History - And Then Some for more information (i.e. if you want to remove older commits).
Oh, and if your working tree is dirty, you have to do a git stash
first, and then a git stash apply
after.
That should “undo” the push.
For an easy revert if it’s just a mistake (perhaps you forked a repo, then ended up pushing to the original instead of to a new one) here’s another possibility:
Obviously swap in that number for the number of the commit you want to return to.
Everything since then will be deleted once you push again. To do that, the next step would be:
How do I remove a Git submodule?
By the way, is there a reason I can’t simply do git submodule rm whatever
?
Since git1.8.3 (April 22d, 2013):
There was no Porcelain way to say “I no longer am interested in this submodule”, once you express your interest in a submodule with “
submodule init
”.
“submodule deinit
” is the way to do so.
The deletion process also uses git rm
(since git1.8.5 October 2013).
The 3-steps removal process would then be:
0. mv a/submodule a/submodule_tmp
1. git submodule deinit -f -- a/submodule
2. rm -rf .git/modules/a/submodule
3. git rm -f a/submodule
# Note: a/submodule (no trailing slash)
# or, if you want to leave it in your working tree and have done step 0
3. git rm --cached a/submodule
3bis mv a/submodule_tmp a/submodule
rm -rf
: This is mentioned in Daniel Schroeder’s answer, and summarized by Eonil in the comments:
This leaves
.git/modules/<path-to-submodule>/
unchanged.
So if you once delete a submodule with this method and re-add them again, it will not be possible because repository already been corrupted.
git rm
: See commit 95c16418:
Currently using “
Let “git rm
” on a submodule removes the submodule’s work tree from that of the superproject and the gitlink from the index.
But the submodule’s section in.gitmodules
is left untouched, which is a leftover of the now removed submodule and might irritate users (as opposed to the setting in.git/config
, this must stay as a reminder that the user showed interest in this submodule so it will be repopulated later when an older commit is checked out).git rm
” help the user by not only removing the submodule from the work tree but by also removing the “submodule.<submodule name>
” section from the.gitmodules
file and stage both.
git submodule deinit
: It stems from this patch:
With “
git submodule init
” the user is able to tell git they care about one or more submodules and wants to have it populated on the next call to “git submodule update
”.
But currently there is no easy way they can tell git they do not care about a submodule anymore and wants to get rid of the local work tree (unless the user knows a lot about submodule internals and removes the “submodule.$name.url
” setting from.git/config
together with the work tree himself).Help those users by providing a ‘
deinit
’ command.
This removes the wholesubmodule.<name>
section from.git/config
either for the given submodule(s) (or for all those which have been initialized if ‘.
’ is given).
Fail if the current work tree contains modifications unless forced.
Complain when for a submodule given on the command line the url setting can’t be found in.git/config
, but nonetheless don’t fail.
This takes care if the (de)initialization steps (.git/config
and .git/modules/xxx
)
Since git1.8.5, the git rm
takes also care of the:
add
’ step which records the url of a submodule in the .gitmodules
file: it is need to removed for you.
git rm --cached path_to_submodule
(no trailing slash)If you forget that last step, and try to add what was a submodule as a regular directory, you would get error message like:
Note: since Git 2.17 (Q2 2018), git submodule deinit is no longer a shell script.
It is a call to a C function.
See commit 2e61273, commit 1342476 (14 Jan 2018) by Prathamesh Chavan (pratham-pc
).
(Merged by Junio C Hamano – gitster
– in commit ead8dbe, 13 Feb 2018)
Via the page Git Submodule Tutorial:
To remove a submodule you need to:
.gitmodules
file.
.gitmodules
changes:git add .gitmodules
.git/config
.
git rm --cached path_to_submodule
(no trailing slash).
.git
directory:rm -rf .git/modules/path_to_submodule
git commit -m "Removed submodule <name>"
rm -rf path_to_submodule
See also: alternative steps below.
Just a note. Since git 1.8.5.2, two commands will do:
As @Mark Cheverton’s answer correctly pointed out, if the second line isn’t used, even if you removed the submodule for now, the remnant .git/modules/the_submodule folder will prevent the same submodule from being added back or replaced in the future. Also, as @VonC mentioned, git rm
will do most of the job on a submodule.
–Update (07/05/2017)–
Just to clarify, the_submodule
is the relative path of the submodule inside the project. For example, it’s subdir/my_submodule
if the submodule is inside a subdirectory subdir
.
As pointed out correctly in the comments and other answers, the two commands (although functionally sufficient to remove a submodule), do leave a trace in the [submodule "the_submodule"]
section of .git/config
(as of July 2017), which can be removed using a third command:
I made a branch called ‘f’ and did a checkout to master. When I tried the git pull
command I got this message:
You have not concluded your merge (MERGE_HEAD exists).
Please, commit your changes before you can merge.
When I try the git status
, it gave me the following:
On branch master
# Your branch and 'origin/master' have diverged,
# and have 1 and 13 different commit(s) each, respectively.
#
# Changes to be committed:
#
# modified: app/assets/images/backward.png
# modified: app/assets/images/forward.png
# new file: app/assets/images/index_background.jpg
# new file: app/assets/images/loading.gif
# modified: app/assets/images/pause.png
# modified: app/assets/images/play.png
# new file: app/assets/javascripts/jquery-ui-bootstrap.js
# new file: app/assets/stylesheets/jquery-ui-bootstrap.css
# modified: app/controllers/friends_controller.rb
# modified: app/controllers/plays_controller.rb
# modified: app/mailers/invite_friends_mailer.rb
# modified: app/mailers/send_plays_mailer.rb
# modified: app/mailers/shot_chart_mailer.rb
# modified: app/views/friends/show_plays.html.erb
# modified: app/views/layouts/application.html.erb
# modified: app/views/plays/_inbox_table.html.erb
# modified: app/views/plays/show.html.erb
# modified: app/views/welcome/contact_form.html.erb
# modified: app/views/welcome/index.html.erb
# modified: log/development.log
# modified: log/restclient.log
# new file: tmp/cache/assets/C1A/C00/sprockets%2Fb7901e0813446f810e560158a1a97066
# modified: tmp/cache/assets/C64/930/sprockets%2F65aa1510292214f4fd1342280d521e4c
# new file: tmp/cache/assets/C73/C40/sprockets%2F96912377b93498914dd04bc69fa98585
# new file: tmp/cache/assets/CA9/090/sprockets%2Fa71992733a432421e67e03ff1bd441d8
# new file: tmp/cache/assets/CCD/7E0/sprockets%2F47125c2ebd0e8b29b6511b7b961152a1
# modified: tmp/cache/assets/CD5/DD0/sprockets%2F59d317902de6e0f68689899259caff26
# modified: tmp/cache/assets/CE3/080/sprockets%2F5c3b516e854760f14eda2395c4ff2581
# new file: tmp/cache/assets/CED/B20/sprockets%2F423772fde44ab6f6f861639ee71444c4
# new file: tmp/cache/assets/D0C/E10/sprockets%2F8d1f4b30c6be13017565fe1b697156ce
# new file: tmp/cache/assets/D12/290/sprockets%2F93ae21f3cdd5e24444ae4651913fd875
# new file: tmp/cache/assets/D13/FC0/sprockets%2F57aad34b9d3c9e225205237dac9b1999
# new file: tmp/cache/assets/D1D/DE0/sprockets%2F5840ff4283f6545f472be8e10ce67bb8
# new file: tmp/cache/assets/D23/BD0/sprockets%2F439d5dedcc8c54560881edb9f0456819
# new file: tmp/cache/assets/D24/570/sprockets%2Fb449db428fc674796e18b7a419924afe
# new file: tmp/cache/assets/D28/480/sprockets%2F9aeec798a04544e478806ffe57e66a51
# new file: tmp/cache/assets/D3A/ED0/sprockets%2Fcd959cbf710b366c145747eb3c062bb4
# new file: tmp/cache/assets/D3C/060/sprockets%2F363ac7c9208d3bb5d7047f11c159d7ce
# new file: tmp/cache/assets/D48/D00/sprockets%2Fe23c97b8996e7b5567a3080c285aaccb
# new file: tmp/cache/assets/D6A/900/sprockets%2Fa5cece9476b21aa4d5f46911ca96c450
# new file: tmp/cache/assets/D6C/510/sprockets%2Fb086a020de3c258cb1c67dfc9c67d546
# new file: tmp/cache/assets/D70/F30/sprockets%2Facf9a6348722adf1ee7abbb695603078
# new file: tmp/cache/assets/DA3/4A0/sprockets%2F69c26d0a9ca8ce383e20897cefe05aa4
# new file: tmp/cache/assets/DA7/2F0/sprockets%2F61da396fb86c5ecd844a2d83ac759b4b
# new file: tmp/cache/assets/DB9/C80/sprockets%2F876fbfb9685b2b8ea476fa3c67ae498b
# new file: tmp/cache/assets/DBD/7A0/sprockets%2F3640ea84a1dfaf6f91a01d1d6fbe223d
# new file: tmp/cache/assets/DC1/8D0/sprockets%2Fe5ee1f1cfba2144ec00b1dcd6773e691
# new file: tmp/cache/assets/DCC/E60/sprockets%2Fd6a95f601456c93ff9a1bb70dea3dfc0
# new file: tmp/cache/assets/DF1/130/sprockets%2Fcda4825bb42c91e2d1f1ea7b2b958bda
# new file: tmp/cache/assets/E23/DE0/sprockets%2Fb1acc25c28cd1fabafbec99d169163d3
# new file: tmp/cache/assets/E23/FD0/sprockets%2Fea3dbcd1f341008ef8be67b1ccc5a9c5
# modified: tmp/cache/assets/E4E/AD0/sprockets%2Fb930f45cfe7c6a8d0efcada3013cc4bc
# new file: tmp/cache/assets/E63/7D0/sprockets%2F77de495a665c3ebcb47befecd07baae6
# modified: tmp/pids/server.pid
#
# Untracked files:
# (use "git add <file>..." to include in what will be committed)
#
# Coachbase/
# log/development.log.orig
# log/restclient.log.orig
What should I do?
OK. The problem is your previous pull failed to merge automatically and went to conflict state. And the conflict wasn’t resolved properly before the next pull.
Undo the merge and pull again.
To undo a merge:
git merge --abort
[Since git version 1.7.4]
git reset --merge
[prior git versions]
Resolve the conflict.
Don’t forget to add and commit the merge.
git pull
now should work fine.
If you are sure that you already resolved all merge conflicts:
And the error will disappear.
I think it’s worth mentioning that there are numerous scenarios in which the message You have not concluded your merge (MERGE_HEAD exists)
could occur, because many people have probably arrived at this page after searching for said message. The resolution will depend on how you got there.
git status
is always a useful starting point.
If you’ve already merged the contents to your satisfaction and are still getting this message, it could be as simple as doing
But again, it really depends on the situation. It’s a good idea to understand the basics before attempting anything (same link Terence posted): Git - Basic Merge Conflicts
I’m not sure why I’m unable to checkout a branch that I had worked on earlier. See the commands below (note: co
is an alias for checkout
):
ramon@ramon-desktop:~/source/unstilted$ git branch -a
* develop
feature/datts_right
feature/user_controlled_menu
feature/user_controlled_site_layouts
master
remotes/origin/HEAD -> origin/master
remotes/origin/develop
remotes/origin/feature/datts_right
remotes/origin/master
ramon@ramon-desktop:~/source/unstilted$ git co feature/user_controlled_site_layouts
error: pathspec 'feature/user_controlled_site_layouts' did not match any file(s) known to git.
I’m not sure what it means, and I can’t seem to find anything I can understand on Google.
How do I checkout that branch, and what may I have done to break this?
UPDATE:
I found this post, and running git show-ref
gives me:
97e2cb33914e763ff92bbe38531d3fd02408da46 refs/heads/develop
c438c439c66da3f2356d2449505c073549b221c1 refs/heads/feature/datts_right
11a90dae8897ceed318700b9af3019f4b4dceb1e refs/heads/feature/user_controlled_menu
c889b37a5ee690986935c9c74b71999e2cf3c6d7 refs/heads/master
c889b37a5ee690986935c9c74b71999e2cf3c6d7 refs/remotes/origin/HEAD
e7c17eb40610505eea4e6687e4572191216ad4c6 refs/remotes/origin/develop
c438c439c66da3f2356d2449505c073549b221c1 refs/remotes/origin/feature/datts_right
c889b37a5ee690986935c9c74b71999e2cf3c6d7 refs/remotes/origin/master
23768aa5425cbf29d10ff24274adad42d90d15cc refs/stash
e572cf91e95da03f04a5e51820f58a7306ce01de refs/tags/menu_shows_published_only
429ebaa895d9d41d835a34da72676caa75902e3d refs/tags/slow_dev
UPDATE on .git
directory (user_controlled_site_layouts
is in the refs/heads/feature folder
):
$ ls .git/refs/heads/feature/
datts_right user_controlled_menu user_controlled_site_layouts
$ cat .git/refs/heads/feature/user_controlled_site_layouts
3af84fcf1508c44013844dcd0998a14e61455034
UPDATE on git show 3af84fcf1508c44013844dcd0998a14e61455034
$ git show 3af84fcf1508c44013844dcd0998a14e61455034
commit 3af84fcf1508c44013844dcd0998a14e61455034
Author: Ramon Tayag <xxx@xxxxx.xxx>
Date: Thu May 12 19:00:03 2011 +0800
Removed site layouts migration
diff --git a/db/schema.rb b/db/schema.rb
index 1218fc8..2040b9f 100755
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -10,7 +10,7 @@
#
# It's strongly recommended to check this file into your version control system.
-ActiveRecord::Schema.define(:version => 20110511012647) do
+ActiveRecord::Schema.define(:version => 20110503040056) do
create_table "attachments", :force => true do |t|
t.string "name"
@@ -205,15 +205,6 @@ ActiveRecord::Schema.define(:version => 20110511012647) do
t.integer "old_id"
end
- create_table "site_layouts", :force => true do |t|
- t.string "name"
- t.text "description"
- t.text "content"
- t.integer "site_id"
- t.datetime "created_at"
- t.datetime "updated_at"
- end
-
create_table "site_styles", :force => true do |t|
t.text "published"
t.datetime "created_at"
Try git fetch
so that your local repository gets all the new info from github. It just takes the information about new branches and no actual code. After that the git checkout
should work fine.
I was getting this error when I tried to checkout new branch:
error: pathspec ‘BRANCH-NAME’ did not match any file(s) known to git.
When I tried git checkout origin/<BRANCH-NAME>
, I got the detached HEAD:
(detached from origin/)
Finally, I did the following to resolve the issue:
I would like to retain (for now) the ability to link Git changesets to workitems stored in TFS.
I already wrote a tool (using a hook from Git) in which I can inject workitemidentifiers into the message of a Git changeset.
However, I would also like to store the identifier of the Git commit (the hash) into a custom TFS workitem field. This way I can examine a workitem in TFS and see what Git changesets are associated with the workitem.
How can I easily retrieve the hash from the current commit from Git?
To turn arbitrary extended object reference into SHA-1, use simply git-rev-parse, for example
or
Sidenote: If you want to turn references (branches and tags) into SHA-1, there is git show-ref
and git for-each-ref
.
If you only want the shortened hash:
Further, using %H is another way to get the long hash.
Another one, using git log:
It’s very similar to the of @outofculture though a bit shorter.
I am introducing myself to Git by following this tutorial:
Everything works fine up until the part where the repo is added to my local machine:
(After replacing USERNAME, NFSNSERVER, and REPOAME with the correct names) I receive the error:
Can you help me get past this step?
Did you init a local Git repository, into which this remote is supposed to be added?
Does your local directory have a .git
folder?
Try git init
.
You’ll get this error if you try to use a Git command when your current working directory is not within a Git repository. That is because, by default, Git will look for a .git
repository directory (inside of the project root?), as pointed out by my answer to “Git won’t show log unless I am in the project directory”:
According to the official Linux Kernel Git documentation,
GIT_DIR
is [an environment variable] set to look for a.git
directory (in the current working directory?) by default:If the
GIT_DIR
environment variable is set then it specifies a path to use instead of the default.git
for the base of the repository.
You’ll either need to cd
into the repository/working copy, or you didn’t initialize or clone a repository in the first place, in which case you need to initialize a repo in the directory where you want to place the repo:
or clone a repository
My problem was that for some hiccups with my OS any command on my local repository ended with “fatal: Not a git repository (or any of the parent directories): .git”, with fsck command included.
The problem was empty HEAD file.
I was able to find actual branch name I’ve worked on in .git/refs/heads and then I did this:
It worked.
I’m new to GitHub. Today I met some issue when I was trying to push my code to GitHub.
Pushing to git@github.com:519ebayproject/519ebayproject.git
To git@github.com:519ebayproject/519ebayproject.git
! [rejected] master -> master (non-fast-forward)
error: failed to push some refs to 'git@github.com:519ebayproject/519ebayproject.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Merge the remote changes (e.g. 'git pull')
hint: before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
I have not pushed anything in the repository yet, so why do I need to pull something?
This can cause the remote repository to lose commits; use it with care.
If you do not wish to merge the remote branch into your local branch (see differences with git diff), and want to do a force push, use the push command with -f
where origin
is the name of your remote repo.
Usually, the command refuses to update a remote ref that is not an ancestor of the local ref used to overwrite it. This flag disables the check. This can cause the remote repository to lose commits; use it with care.
As the message tells you,
Merge the remote changes (e.g. ‘git pull’)
Use git pull
to pull the latest changes from the remote repository to your local repository. In this case, pulling changes will require a merge because you have made changes to your local repository.
I’ll provide an example and a picture to explain. Let’s assume your last pull from origin/branch was at Commit B. You have completed and committed some work (Commit C). At the same time, someone else has completed their work and pushed it to origin/branch (Commit D). There will need to be a merge between these two branches.
Because you are the one that wants to push, Git forces you to perform the merge. To do so, you must first pull the changes from origin/branch.
After completing the merge, you will now be allowed to fast-forward origin/branch to Commit E by pushing your changes.
Git requires that you handle merges yourself, because a merge may lead to conflicts.
I guess most of you, developers, use any VCS, and I hope some of you use Git. Do you have any tip or trick how to get a download URL for a single file in a repository?
I don’t want the URL for displaying the raw file; in case of binaries it’s for nothing.
http://support.github.com/discussions/feature-requests/41-download-single-file
Is it even possible to use GitHub as a “download server”?
If we decide to switch to Google Code, is the mentioned functionality presented here?
Or is there any free-of-charge hosting and VCS for open-source projects?
Git does not support downloading parts of the repository. You have to download all of it. But you should be able to do this with GitHub.
When you view a file it has a link to the “raw” version. The URL is constructed like so
By filling in the blanks in the URL, you can use Wget or cURL (with the -L
option, see below) or whatever to download a single file. Again, you won’t get any of the nice version control features used by Git by doing this.
Update: I noticed you mention this doesn’t work for binary files. You probably shouldn’t use binary files in your Git repository, but GitHub has a download section for each repository that you can use to upload files. If you need more than one binary, you can use a .zip file. The URL to download an uploaded file is:
Note that the URLs given above, from the links on github.com
, will redirect to raw.githubusercontent.com
. You should not directly use the URL given by this HTTP 302 redirect because, per RFC 2616: “Since the redirection might be altered on occasion, the client SHOULD continue to use the Request-URI for future requests.”
Raw
button.
You can use the V3 API to get a raw file like this (you’ll need an OAuth token):
curl -H 'Authorization: token INSERTACCESSTOKENHERE' -H 'Accept: application/vnd.github.v3.raw' -O -L https://api.github.com/repos/owner/repo/contents/path
All of this has to go on one line. The -O
option saves the file in the current directory. You can use -o filename
to specify a different filename.
To get the OAuth token follow the instructions here: https://help.github.com/articles/creating-an-access-token-for-command-line-use
I’ve written this up as a gist as well: https://gist.github.com/madrobby/9476733
I staged a few changes to be committed; how can I see the diff of all files which are staged for the next commit? I’m aware of git status, but I’d like to see the actual diffs - not just the names of files which are staged.
I saw that the git-diff(1) man page says
git diff [–options] [–] […]
This form is to view the changes you made relative to the index (staging area for the next commit). In other words, the differences are what you could tell git to further add to the index but you still haven’t. You can stage these changes by using git-add(1).
Unfortunately, I can’t quite make sense of this. There must be some handy one-liner which I could create an alias for, right?
It should just be:
--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.
A simple graphic makes this clearer:
git diff
Shows the changes between the working directory and the index. This shows what has been changed, but is not staged for a commit.
git diff –cached
Shows the changes between the index and the HEAD (which is the last commit on this branch). This shows what has been added to the index and staged for a commit.
git diff HEAD
Shows all the changes between the working directory and HEAD (which includes changes in the index). This shows all the changes since the last commit, whether or not they have been staged for commit or not.
Also:
There is a bit more detail on 365Git.
If you’d be interested in a visual side-by-side view, the diffuse visual diff tool can do that. It will even show three panes if some but not all changes are staged. In the case of conflicts, there will even be four panes.
Invoke it with
in your Git working copy.
If you ask me, the best visual differ I’ve seen for a decade. Also, it is not specific to Git: It interoperates with a plethora of other VCS, including SVN, Mercurial, Bazaar, …
See also: Show both staged & working tree in git diff?
My initial commit contained some log files. I’ve added *log
to my .gitignore
, and now I want to remove the log files from my repository.
will remove a file from the repository, but will also remove it from the local file system.
How can I remove this file from the repo without deleting my local copy of the file?
From the man file:
When --cached
is given, the staged content has to match either the tip of the branch or the file on disk, allowing the file to be removed from just the index.
So, for a single file:
and for a single directory:
To remove an entire folder from the repo (like Resharper files), do this:
I had committed some resharper files, and did not want those to persist for other project users.
You can also remove files from the repository based on your .gitignore without deleting them from the local file system :
Or, alternatively, on Windows Powershell:
I’m trying to put a submodule into a repo. The problem is that when I clone the parent repo, the submodule folder is entirely empty.
Is there any way to make it so that git clone parent_repo
actually puts data in the submodule folder?
For example, http://github.com/cwolves/sequelize/tree/master/lib/, nodejs-mysql-native
is pointing at an external git submodule, but when I checkout the sequelize
project, that folder is empty.
With version 2.13 of Git and later, --recurse-submodules
can be used instead of --recursive
:
Editor’s note: -j8
is an optional performance optimization that became available in version 2.8, and fetches up to 8 submodules at a time in parallel — see man git-clone
.
With version 1.9 of Git up until version 2.12 (-j
flag only available in version 2.8+):
With version 1.6.5 of Git and later, you can use:
For already cloned repos, or older Git versions, use:
You have to do two things before a submodule will be filled:
Due to some bad cherry-picking, my local Git repository is currently five commits ahead of the origin, and not in a good state. I want to get rid of all these commits and start over again.
Obviously, deleting my working directory and re-cloning would do it, but downloading everything from GitHub again seems like overkill, and not a good use of my time.
Maybe git revert
is what I need, but I don’t want to end up 10 commits ahead of the origin (or even six), even if it does get the code itself back to the right state. I just want to pretend the last half-hour never happened.
Is there a simple command that will do this? It seems like an obvious use case, but I’m not finding any examples of it.
Note that this question is specifically about commits, not about:
If your excess commits are only visible to you, you can just do git reset --hard origin/<branch_name>
to move back to where the origin is. This will reset the state of the repository to the previous commit, and it will discard all local changes.
Doing a git revert
makes new commits to remove old commits in a way that keeps everyone’s history sane.
Simply delete your local master branch and recreate it like so:
Try:
to reset your head to wherever you want to be. Use gitk to see which commit you want to be at. You can do reset within gitk as well.
I was able to clone a copy of this repo over HTTPS authenticated. I’ve made some commits and want to push back out to the GitHub server. Using Cygwin on Windows 7 x64.
C:\cygwin\home\XPherior\Code\lunch_call>git push
Password:
error: The requested URL returned error: 403 while accessing https://MichaelDrog
alis@github.com/derekerdmann/lunch_call.git/info/refs
fatal: HTTP request failed
Also set it up with verbose mode. I’m still pretty baffled.
C:\cygwin\home\XPherior\Code\lunch_call>set GIT_CURL_VERBOSE=1
C:\cygwin\home\XPherior\Code\lunch_call>git push
Password:
* Couldn't find host github.com in the _netrc file; using defaults
* About to connect() to github.com port 443 (#0)
* Trying 207.97.227.239... * 0x23cb740 is at send pipe head!
* Connected to github.com (207.97.227.239) port 443 (#0)
* successfully set certificate verify locations:
* CAfile: C:\Program Files (x86)\Git/bin/curl-ca-bundle.crt
CApath: none
* SSL connection using AES256-SHA
* Server certificate:
* subject: 2.5.4.15=Private Organization; 1.3.6.1.4.1.311.60.2.1.3=US; 1.
3.6.1.4.1.311.60.2.1.2=California; serialNumber=C3268102; C=US; ST=California; L
=San Francisco; O=GitHub, Inc.; CN=github.com
* start date: 2011-05-27 00:00:00 GMT
* expire date: 2013-07-29 12:00:00 GMT
* subjectAltName: github.com matched
* issuer: C=US; O=DigiCert Inc; OU=www.digicert.com; CN=DigiCert High Ass
urance EV CA-1
* SSL certificate verify ok.
> GET /derekerdmann/lunch_call.git/info/refs?service=git-receive-pack HTTP/1.1
User-Agent: git/1.7.4.3282.g844cb
Host: github.com
Accept: */*
Pragma: no-cache
< HTTP/1.1 401 Authorization Required
< Server: nginx/1.0.4
< Date: Thu, 15 Sep 2011 22:44:41 GMT
< Content-Type: text/plain
< Connection: keep-alive
< Content-Length: 55
< WWW-Authenticate: Basic realm="GitHub"
<
* Ignoring the response-body
* Expire cleared
* Connection #0 to host github.com left intact
* Issue another request to this URL: 'https://MichaelDrogalis@github.com/dereker
dmann/lunch_call.git/info/refs?service=git-receive-pack'
* Couldn't find host github.com in the _netrc file; using defaults
* Re-using existing connection! (#0) with host github.com
* Connected to github.com (207.97.227.239) port 443 (#0)
* 0x23cb740 is at send pipe head!
* Server auth using Basic with user 'MichaelDrogalis'
> GET /derekerdmann/lunch_call.git/info/refs?service=git-receive-pack HTTP/1.1
Authorization: Basic XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
User-Agent: git/1.7.4.3282.g844cb
Host: github.com
Accept: */*
Pragma: no-cache
< HTTP/1.1 401 Authorization Required
< Server: nginx/1.0.4
< Date: Thu, 15 Sep 2011 22:44:41 GMT
< Content-Type: text/plain
< Connection: keep-alive
< Content-Length: 55
* Authentication problem. Ignoring this.
< WWW-Authenticate: Basic realm="GitHub"
* The requested URL returned error: 401
* Closing connection #0
* Couldn't find host github.com in the _netrc file; using defaults
* About to connect() to github.com port 443 (#0)
* Trying 207.97.227.239... * 0x23cb740 is at send pipe head!
* Connected to github.com (207.97.227.239) port 443 (#0)
* successfully set certificate verify locations:
* CAfile: C:\Program Files (x86)\Git/bin/curl-ca-bundle.crt
CApath: none
* SSL re-using session ID
* SSL connection using AES256-SHA
* old SSL session ID is stale, removing
* Server certificate:
* subject: 2.5.4.15=Private Organization; 1.3.6.1.4.1.311.60.2.1.3=US; 1.
3.6.1.4.1.311.60.2.1.2=California; serialNumber=C3268102; C=US; ST=California; L
=San Francisco; O=GitHub, Inc.; CN=github.com
* start date: 2011-05-27 00:00:00 GMT
* expire date: 2013-07-29 12:00:00 GMT
* subjectAltName: github.com matched
* issuer: C=US; O=DigiCert Inc; OU=www.digicert.com; CN=DigiCert High Ass
urance EV CA-1
* SSL certificate verify ok.
* Server auth using Basic with user 'MichaelDrogalis'
> GET /derekerdmann/lunch_call.git/info/refs HTTP/1.1
Authorization: Basic xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
User-Agent: git/1.7.4.3282.g844cb
Host: github.com
Accept: */*
Pragma: no-cache
* The requested URL returned error: 403
* Expire cleared
* Closing connection #0
error: The requested URL returned error: 403 while accessing https://MichaelDrog
alis@github.com/derekerdmann/lunch_call.git/info/refs
fatal: HTTP request failed
These are the versions of git and curl that I have:
C:\Users\XPherior>git --version
git version 1.7.4.msysgit.0
C:\Users\XPherior>curl --version
curl 7.21.7 (amd64-pc-win32) libcurl/7.21.7 OpenSSL/0.9.8r zlib/1.2.5
Protocols: dict file ftp ftps gopher http https imap imaps ldap pop3 pop3s rtsp
smtp smtps telnet tftp
Features: AsynchDNS GSS-Negotiate Largefile NTLM SSL SSPI libz
I just got the same problem and just figured out what’s cause.
Github seems only supports ssh way to read&write the repo, although https way also displayed ‘Read&Write’.
So you need to change your repo config on your PC to ssh way:
.git/config
file under your repo directory
url=
entry under section [remote "origin"]
url=https://MichaelDrogalis@github.com/derekerdmann/lunch_call.git
to url=ssh://git@github.com/derekerdmann/lunch_call.git
. that is, change all the texts before @
symbol to ssh://git
config
file and quit. now you could use git push origin master
to sync your repo on GitHub
To definitely be able to login using https
protocol, you should first set your authentication credential to the git Remote URI:
Then you’ll be asked for a password when trying to git push
.
In fact, this is on the http authentication format. You could set a password too:
You should be aware that if you do this, your github password will be stored in plaintext in your .git directory, which is obviously undesirable.
One small addition to Sean’s answer.
Instead of editing .git/config
file manually, you can use git remote set-url
command.
In your case it should be:
I find it easier and cleaner, than messing around with dot-files.
For some reason, I can’t push now, whereas I could do it yesterday. Maybe I messed up with configs or something.
This is what happens:
When I use the git push origin master
What my working directory and remote repository looks like:
If the GitHub repo has seen new commits pushed to it, while you were working locally, I would advise using:
The full syntax is:
That way, you would replay (the --rebase
part) your local commits on top of the newly updated origin/master
(or origin/yourBranch
: git pull origin yourBranch
).
See a more complete example in the chapter 6 Pull with rebase of the Git Pocket Book.
I would recommend a:
That would establish a tracking relationship between your local master branch and its upstream branch.
After that, any future push for that branch can be done with a simple:
See “Why do I need to explicitly push a new branch?”.
Since the OP already reset and redone its commit on top of origin/master
:
git reset --mixed origin/master
git add .
git commit -m "This is a new commit for what I originally planned to be amended"
git push origin master
There is no need to pull --rebase
.
Note: git reset --mixed origin/master
can also be written git reset origin/master
, since the --mixed
option is the default one when using git reset
.
Did anyone try:
That should solve the problem.
EDIT: Based on @Mehdi ‘s comment below I need to clarify something about —force pushing
. The git command above works safely only for the first commit. If there were already commits, pull requests or branches in previous, this resets all of it and set it from zero. If so, please refer @VonC ‘s detailed answer for better solution.
If you just used git init
and have added your files with git add .
or something similar and have added your remote branch it might be that you just haven’t committed (git commit -m 'commit message'
) anything locally to push to the remote… I just had this error and that was my issue.
I’ve just generated my RSA key pair, and I wanted to add that key to GitHub.
I tried cd id_rsa.pub
and id_rsa.pub
, but no luck. How can I access my SSH public key?
cat ~/.ssh/id_rsa.pub
or cat ~/.ssh/id_dsa.pub
You can list all the public keys you have by doing:
$ ls ~/.ssh/*.pub
Copy the key to your clipboard.
Warning: it’s important to copy the key exactly without adding newlines or whitespace. Thankfully the pbcopy command makes it easy to perform this setup perfectly.
And you can paste it wherever you need.
To get a better idea of the whole process, check this: Generating SSH Keys.
You may try to run the following command to show your RSA fingerprint:
or public key:
If you’ve the message: ‘The agent has no identities.’, then you’ve to generate your RSA key by ssh-keygen
first.
How can I view any local commits I’ve made, that haven’t yet been pushed to the remote repository? Occasionally, git status
will print out that my branch is X commits ahead of origin/master
, but not always.
Is this a bug with my install of Git, or am I missing something?
You can also view the diff using the same syntax
If you want to see all commits on all branches that aren’t pushed yet, you might be looking for something like this:
And if you only want to see the most recent commit on each branch, and the branch names, this:
You can show all commits that you have locally but not upstream with
@{u}
or @{upstream}
means the upstream branch of the current branch (see git rev-parse --help
or git help revisions
for details).
How can I uncommit my last commit in git?
Is it
or
?
If you aren’t totally sure what you mean by “uncommit” and don’t know if you want to use git reset
, please see “Revert to a previous Git commit”.
If you’re trying to understand git reset
better, please see “Can you explain what”git reset" does in plain English?".
If you know you want to use git reset
, it still depends what you mean by “uncommit”. If all you want to do is undo the act of committing, leaving everything else intact, use:
If you want to undo the act of committing and everything you’d staged, but leave the work tree (your files intact):
And if you actually want to completely undo it, throwing away all uncommitted changes, resetting everything to the previous commit (as the original question asked):
The original question also asked it’s HEAD^
not HEAD
. HEAD
refers to the current commit - generally, the tip of the currently checked-out branch. The ^
is a notation which can be attached to any commit specifier, and means “the commit before”. So, HEAD^
is the commit before the current one, just as master^
is the commit before the tip of the master branch.
Here’s the portion of the git-rev-parse documentation describing all of the ways to specify commits (^
is just a basic one among many).
To keep the changes from the commit you want to undo
To destroy the changes from the commit you want to undo
You can also say
to go back 2 commits.
Edit: As charsi mentioned, if you are on Windows you will need to put HEAD or commit hash in quotes.
How can I stash only one of multiple changed files on my branch?
Update: the following answer is for git before git 2.13. For git 2.13 and over, check out another answer further down.
Warning
As noted in the comments, this puts everything into the stash, both staged and unstaged. The –keep-index just leaves the index alone after the stash is done. This can cause merge conflicts when you later pop the stash.
This will stash everything that you haven’t previously added. Just git add
the things you want to keep, then run it.
For example, if you want to split an old commit into more than one changeset, you can use this procedure:
git rebase -i <last good commit>
edit
.
git reset HEAD^
git add <files you want to keep in this change>
git stash --keep-index
git add
any changes.
git commit
git stash pop
git rebase --continue
You can also use git stash save -p "my commit message"
. This way you can select which hunks should be added to stash, whole files can be selected as well.
You’ll be prompted with a few actions for each hunk:
y - stash this hunk
n - do not stash this hunk
q - quit; do not stash this hunk or any of the remaining ones
a - stash this hunk and all later hunks in the file
d - do not stash this hunk or any of the later hunks in the file
g - select a hunk to go to
/ - search for a hunk matching the given regex
j - leave this hunk undecided, see next undecided hunk
J - leave this hunk undecided, see next hunk
k - leave this hunk undecided, see previous undecided hunk
K - leave this hunk undecided, see previous hunk
s - split the current hunk into smaller hunks
e - manually edit the current hunk
? - print help
Since git is fundamentally about managing a all repository content and index (and not one or several files), git stash
deals, not surprisingly, with the all working directory.
Actually, since Git 2.13 (Q2 2017), you can stash individual files, with git stash push
:
Whenpathspec
is given to ‘git stash push
’, the new stash records the modified states only for the files that match the pathspec
See “Stash changes to specific files” for more.
The test case is self-explanatory:
test_expect_success 'stash with multiple pathspec arguments' '
>foo &&
>bar &&
>extra &&
git add foo bar extra &&
git stash push -- foo bar &&
test_path_is_missing bar &&
test_path_is_missing foo &&
test_path_is_file extra &&
git stash pop &&
test_path_is_file foo &&
test_path_is_file bar &&
test_path_is_file extra
The original answer (below, June 2010) was about manually selecting what you want to stash.
Casebash comments:
This (the stash --patch
original solution) is nice, but often I’ve modified a lot of files so using patch is annoying
bukzor’s answer (upvoted, November 2011) suggests a more practical solution, based on
git add
+ git stash --keep-index
.
Go see and upvote his answer, which should be the official one (instead of mine).
About that option, chhh points out an alternative workflow in the comments:
you should “
git reset --soft
” after such a stash to get your clear staging back:
In order to get to the original state - which is a clear staging area and with only some select un-staged modifications, one could softly reset the index to get (without committing anything like you - bukzor - did).
(Original answer June 2010: manual stash)
Yet, git stash save --patch
could allows you to achieve the partial stashing you are after:
With
--patch
, you can interactively select hunks from in the diff between HEAD and the working tree to be stashed.
The stash entry is constructed such that its index state is the same as the index state of your repository, and its worktree contains only the changes you selected interactively. The selected changes are then rolled back from your worktree.
However that will save the full index (which may not be what you want since it might include other files already indexed), and a partial worktree (which could look like the one you want to stash).
might be a better fit.
If --patch
doesn’t work, a manual process might:
For one or several files, an intermediate solution would be to:
git stash
git stash
# this time, only the files you want are stashed
git stash pop stash@{1}
# re-apply all your files modifications
git checkout -- afile
# reset the file to the HEAD content, before any local modifications