Reputation: 9591
Let's say I have a repository and it's a straight line. I checkout the very first commit and I add a file and commit it. Will this create a new branch implicitly? If it does and I merge it back into the parent, what happens to all the commits that are based on the parent? How do I go back in the history make a change and have it propagate to all future commits based off of it?
Upvotes: 0
Views: 175
Reputation: 124648
I checkout the very first commit and I add a file and commit it. Will this create a new branch implicitly?
No. In Git, when you checkout a commit, it updates the content of your working directory to match the content of that commit. You can look around and play with it, but you cannot commit changes. This is called the detached HEAD state.
In this state you can create a branch with git checkout -b branchname
, so that you will be in a proper branch, commit changes, and diverge from the original branch.
If it does and I merge it back into the parent, what happens to all the commits that are based on the parent?
Let's say you created a branch from the 1st commit, and you want to merge this independent branch into the original. The commits in the original branch don't change. The unique commits in the new branch will be appended to the original branch, their changes will be applied to the files.
The result will look something like this:
$ git log --graph --oneline --decorate
* 69d6cc5 (HEAD, master) Merge branch 'mybranch'
|\
| * 01ca942 (mybranch) added something
* | e715c4a 3rd commit
* | 4f88705 2nd commit
|/
* e7a9e79 Initial commit
How do I go back in the history make a change and have it propagate to all future commits based off of it?
This is called rebasing, and it's best to avoid as much as possible. Rebasing rewrites the history. If you think about it this is against the spirit of version control, where existing commits should be left alone, immutable, and all changes should be incremental. However, Git let's you do this, you're the boss. This sequence of commands will do it:
# create branch from a specific older commit
git checkout -b mybranch SOMESHA
# work work work
git commit -m 'fixed something important'
# switch to the master branch
git checkout master
# rebase on top of mybranch
git rebase mybranch
That's it. This will rewind the history of master
to the tip of mybranch
, and apply all the changes that happened in master
after SOMESHA
one by one.
Sticking with the earlier example repo, the result will look something like this:
$ git log --graph --oneline --decorate
* 7e3dd9d (HEAD, master) 3rd commit
* 027589b 2nd commit
* 01ca942 (mybranch) added something
* e7a9e79 Initial commit
Notice that the first commit and the one in mybranch
have the same SHA1 as earlier, but the 2nd and 3rd commits have different SHA1. Even though their content is actually the same. We rewrote history. Whether you merge or rebase, the end result should be the same in terms of the content of the files.
Another reason to avoid rebasing is that after you do this, you must tell all users who have cloned your repository to force update their clones. This can be confusing, and a serious inconvenience for them.
Upvotes: 1
Reputation: 1773
When you check out a commit (as opposed to a branch), you go into ‘detached HEAD’ state. This means that when you make subsequent changes to your HEAD (using git commit
, git reset
, etc.), this will not automatically update any branch. Also, your HEAD will not be visible in gitk
once it isn't the parent of a branch or tag any more, which might be confusing.
Your master branch isn't affected by this, which means you will lose all work done in this state once you check out the master branch (unless you write down the commit id or retrieve it from the reflog).
If you want to create a new branch, you will have to do so explicitly:
git checkout -b new_branch_name
You can merge your changes back into the master branch as usual:
git merge master new_branch_name
How do I go back in the history make a change and have it propagate to all future commits based off of it?
There are two ways to achieve this:
git rebase -i
and change the command from pick
to edit
for the appropriate line(s). Make sure you don't delete any lines here since that will drop the commits.git rebase new_branch_name master
to rebase your old master branch on top of the new branch. Optionally do git branch -d new_branch_name
.You shouldn't ever change the history of a public repository, though.
Upvotes: 0
Reputation: 39
I checkout the very first commit and I add a file and commit it. Will this create a new branch implicitly?
It gets appended to the end of the current LOCAL branch. Assuming you have a REMOTE branch, they will differ.
If it does and I merge it back into the parent, what happens to all the commits that are based on the parent
The LOCAL and REMOTE branches differ, you will have to merge/rebase when you want them to be in sync again, and push the local branch to the remote one to update it to everyone else.
How do I go back in the history make a change and have it propagate to all future commits based off of it
You don't, if you rewrite history locally and push it you will have to tell everyone else that uses the remote branch to delete their local branch and pull yours. You should never do that, just update your local branch with a merge or a rebase just before pushing it to REMOTE to everyone else.
Upvotes: 0