19

Could anyone tell me how to clone the first commit? I don't want to delete recent commits, just make a clone copy of the initial state so I can grab some of the files.

Wim Coenen
  • 66,094
  • 13
  • 157
  • 251
igniteflow
  • 8,404
  • 10
  • 38
  • 46
  • a git repository can have several 'first commits' – knittl Jun 22 '10 at 12:14
  • 14
    Okay, you guys, don't make such a stink about the first commit thing. There's always at least one root commit, and it's very rare for there to be multiple, especially in a repository of a user asking a basic question like this. – Cascabel Jun 22 '10 at 13:39

5 Answers5

16

If by "first commit", you mean the parent commit of a branch that does not have any parents itself, then you want to use the git-rev-list to do that. Just use

git rev-list --max-parents=0 HEAD

That will get your "Initial commit" for the current HEAD. Use master if you list, or any other child revision specification. wrap that in $(...) in order to use that in an expression, such as:

git checkout $(git rev-list --max-parents=0 HEAD)

Jesse Buchanan
  • 1,099
  • 1
  • 9
  • 24
Michael Erickson
  • 3,881
  • 2
  • 20
  • 16
  • 2
    Thanks, this is the only answer that covers the general case without an intermediate copy/paste step. – Jesse Buchanan Mar 23 '14 at 17:00
  • 1
    OP wasn't trying to checkout the first commit. He wanted to clone the repo in the state it was in after the first commit. i.e. he didn't want all the other commits. There's lots of reasons this might be valid. We're working with micro services. The commits that initialised our report building service can be used for our GraphQL service. We want the VS Code setup for running mongo and python in containers during development. We don't want all the stuff that actually produces pdf's. – Aidan Ewen Aug 09 '21 at 09:46
14

Updated 2018 answer: Use your own symbolic ref, ie. tag. And start using describe and annotated tags.

git tag -a -m "Initial version" root $( git rev-list --all | tail -n 1 )
git describe

Output description for a repo that never received a tag but occasionally committed to since 2011 with above tag:

root-1090-g88a80e93

If you want to discard all other history on the other hand I've never needed that, it is easy enough to copy the initial set. I can see the use-case if you wanted to refer to the original 'root' commit and stamps though. Maybe look at how ie. BFG work, --depth or GIT 2.19 its new clone --filter. [3]


I think I want to do the same thing. Checkout the initial commit, and branch from there. I'm not sure with the answer accepted. But I guess it could (partly) fullfil the original question. After reading this thread, I however will go with some bash scripting around

git log --pretty=oneline  master | tail -1

I hoped there would be some commit- or tree-ish reference for this. Maybe to list nodes marked as root, but I suppose GIT by itself does not track this. So this method only works on a repository with only one root commit.

The 2017 and 2018 updates are that there is a better option to git log, using git rev-list but that suffer from the same problem. They simply use the trailing item of a list of commits still.

You can checkout the 'root commit' for a repository with only one root with the following, and it works for most of the repositories. But it is a hack, and it would be better to review your system why and where it needs to mark the root commits. And simply tag it or record it.

You can checkout the first commit in a repo with one root with the following command:

git checkout $( git rev-list --all | tail -n 1 )

or (GIT <1.8.1):

git checkout $( git log --pretty=oneline | tail -n 1 | sed 's/ .*$//' )

See git-revlist and also Using git, how do I go back to first commit then go through the history?.

[3]:

mpe
  • 148
  • 1
  • 8
  • 3
    If you used `git rev-list --all` instead of `git log --pretty=oneline master`, you wouldn't have to parse out the commit message because it returns just shas. See my answer to [Using git, how do I go back to first commit](http://superuser.com/a/773366/180163) – KyleMit Jun 25 '14 at 15:54
8

To answer the question I think you meant to ask:

You can get your entire repository into the state of the first commit with:

git checkout <commit SHA1>

After you're done messing around, you can do git checkout master to get back to where you were.

And you can get individual files into their state from the first commit with:

git checkout <commit SHA1> <file or directory> ...

Again, after you're done, you can do git checkout master <file or directory> to get back to where you were.

There's no need to "clone" a commit (by which I assume you mean clone the repository, and check out the first commit?). Of course, if for some reason you couldn't bear to modify any files in your repository (e.g. don't want to make your build out of date) you could of course clone it, then do the exact same thing in the cloned repo.

Cascabel
  • 479,068
  • 72
  • 370
  • 318
  • OP wants the repo in the state it was in after the first commit. He doesn't want all the subsequent commits. He wasn't simply trying to checkout a specific (first) commit. – Aidan Ewen Aug 09 '21 at 09:48
3

Use command:

git fetch --depth=1 ../testrepo/.git $SHA1

This will only clone the certain commit. You can checkout this answer for more details.

ramwin
  • 5,803
  • 3
  • 27
  • 29
-1

I think all you need to do is create a new branch from the original commit you want, check that out, and then merge back into the HEAD of the branch you're working on.

If abcxyz... is the SHA1 of the commit you want and you're working in the master branch, this is generally what you'd want to do:

git branch oldskool abcxyz... # creates a new branch called oldskool from the commit
git checkout oldskool
#make changes
git rebase master #bring the oldskool branch up to the HEAD of the master branch (shouldn't overwrite the changes in the files you edited)
git checkout master
git merge oldskool
brycemcd
  • 4,343
  • 3
  • 26
  • 29
  • You're creating oldskool from an ancestor of master, so the rebase is just going to fast-forward it, and then the merge is a no-op. No change to master. If you skip the rebase, the merge will also be a fast-forward, and again, no change to master. – Cascabel Jun 22 '10 at 15:00