I think there are a few questions that you ask here. The first one looks like "How do I restore file1.txt ?" Assuming your revision schedule looks something like this:
M (master) o -- o --- o ------o HEAD \ / (b1) o -- o -- o ABC
You can get the previous copy of file1.txt via git checkout :
git checkout HEAD~1 -- file1.txt
This will resurrect file1.txt and generate it in your working copy. You can git commit and the file will return. Note: HEAD~1 says that the first HEAD parent indicates the state of the master before merging b1. If you know the commit id, you can use it instead of HEAD~1 .
Another question that you seem to be asking is, "What should I have done in branches b1 to avoid this?" The most obvious choice would not be to delete file1.txt in the first place. But let us suppose that you thought what you needed and decided that the choice was the wrong one. Then suppose that you did not split branch b1 by clicking on it any changes. If you notice that you deleted the file immediately, you can do the following:
git checkout HEAD~1 -- file1.txt git commit --amend
This will say: "Give me the file1.txt file, and then merge this file into the last commit." This makes it appear as if you never deleted the file in the first place.
If you did not notice that the file was deleted immediately, and there were several commits between you, you may need to use git rebase to fix the errors.
If you deleted the file in your own commit, you can use git rebase -i to remove the commit from the branch history. Suppose B is the commit that deleted the file, and this is the only thing done in this case. While on b1 you run something like:
git rebase -i B~1
Delete the line containing the offensive commit ( B ), save and exit. Your thread just rewrote the story without B For example, I ran git rebase -i , and this was shown in the editor:
pick 40f76a7 removed bar pick 30a25f5 modified foo
Then I dropped 40f76a7 from the list and then left me with:
pick 30a25f5 modified foo
The story now looks like this after the merge:
M (master) o -- o --- o ------o HEAD \ / (b1) o ------- o AC'
Note that the commit identifier C' is different from C because B no longer exists and the parent sha1s are part of the commit identifier. IOW, sha1 of C has changed because we rewrote the story.
If you deleted file1.txt and had a bunch of other changes in the same commit, then there are a few more steps. First return the file and commit it:
git checkout B~1 -- file1.txt git commit -m "Reinstate file1.txt"
Let me invoke the new commit D Our revision schedule now looks like
M (master) o -- o --- o -----------o HEAD \ (b1) o -- o -- o -- o ABCD
Now do:
git rebase -i B~1
And move the line containing the commit D identifier right after commit id B and change pick to squash . For example, I get this when running git rebase -i B~1 :
pick 40f76a7 removed bar plus other changes pick 30a25f5 modified foo pick 6177cb7 add bar
6177cb7 is a fix that restores bars. So I move it just below 40f76a7 and change the command to squash :
pick 40f76a7 removed bar plus other changes squash 6177cb7 fix bar pick 30a25f5 modified foo
Save and exit. He will ask you to fix the commit message. Do this. When it's over, you get a story that looks like this:
M (master) o -- o --- o -----------o HEAD \ (b1) o -- o -- o AB' C'
New B' no longer removes file1.txt . At this point, you are ready to merge with the master.
A few concluding remarks. Be careful with git rebase . You may lose history if you are not careful. Be sure to read the git rebase man page. There is a lot of useful information. Note: all this work with git rebase necessary only if you want to delete the fact that you deleted the file from the history. If you agree with the commit showing that you are returning the file, then by all means, use git checkout to restore the file and commit it. This is much less tiring and easier for a new git user. git rebase pretty advanced and requires some practice. However, if you invest time and study well, it is really useful.